VirtualBox

Changeset 27118 in vbox for trunk/src/VBox/Additions


Ignore:
Timestamp:
Mar 5, 2010 5:41:52 PM (15 years ago)
Author:
vboxsync
Message:

common/VBoxGuest: fixed the ballooning todos

Location:
trunk/src/VBox/Additions/common/VBoxGuest
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp

    r27106 r27118  
    366366 * @returns VBox status code.
    367367 * @param   pDevExt         The device extension.
     368 * @param   pSession        The session.
    368369 * @param   cBalloonChunks  The new size of the balloon in chunks of 1MB.
    369370 */
    370 static int vboxGuestSetBalloonSizeKernel(PVBOXGUESTDEVEXT pDevExt, uint32_t cBalloonChunks)
     371static int vboxGuestSetBalloonSizeKernel(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t cBalloonChunks)
    371372{
    372373    int rc = VINF_SUCCESS;
     
    483484    if (fInflate)
    484485    {
    485         if (   pSession->MemBalloon.cChunks > pDevExt->MemBalloon.cMaxChunks - 1
     486        if (   pDevExt->MemBalloon.cChunks > pDevExt->MemBalloon.cMaxChunks - 1
    486487            || pDevExt->MemBalloon.cMaxChunks == 0 /* If called without first querying. */)
    487488        {
    488489            LogRel(("vboxGuestSetBalloonSize: cannot inflate balloon, already have %u chunks (max=%u)\n",
    489                     pSession->MemBalloon.cChunks, pDevExt->MemBalloon.cMaxChunks));
     490                    pDevExt->MemBalloon.cChunks, pDevExt->MemBalloon.cMaxChunks));
    490491            return VERR_INVALID_PARAMETER;
    491492        }
    492493
    493         if (!pSession->MemBalloon.paMemObj)
    494         {
    495             pSession->MemBalloon.paMemObj = (PRTR0MEMOBJ)RTMemAlloc(sizeof(RTR0MEMOBJ) * pDevExt->MemBalloon.cMaxChunks);
    496             if (!pSession->MemBalloon.paMemObj)
     494        if (!pDevExt->MemBalloon.paMemObj)
     495        {
     496            pDevExt->MemBalloon.paMemObj = (PRTR0MEMOBJ)RTMemAlloc(sizeof(RTR0MEMOBJ) * pDevExt->MemBalloon.cMaxChunks);
     497            if (!pDevExt->MemBalloon.paMemObj)
    497498            {
    498499                LogRel(("VBoxGuestSetBalloonSizeFromUser: no memory for paMemObj!\n"));
     
    500501            }
    501502            for (i = 0; i < pDevExt->MemBalloon.cMaxChunks; i++)
    502                 pSession->MemBalloon.paMemObj[i] = NIL_RTR0MEMOBJ;
     503                pDevExt->MemBalloon.paMemObj[i] = NIL_RTR0MEMOBJ;
    503504        }
    504505    }
    505506    else
    506507    {
    507         if (pSession->MemBalloon.cChunks == 0)
     508        if (pDevExt->MemBalloon.cChunks == 0)
    508509        {
    509510            AssertMsgFailed(("vboxGuestSetBalloonSize: cannot decrease balloon, already at size 0\n"));
     
    519520        if (   fInflate
    520521            && !pMemObj
    521             && pSession->MemBalloon.paMemObj[i] == NIL_RTR0MEMOBJ)
    522             pMemObj = &pSession->MemBalloon.paMemObj[i]; /* found free object pointer */
    523         if (RTR0MemObjAddressR3(pSession->MemBalloon.paMemObj[i]) == u64ChunkAddr)
     522            && pDevExt->MemBalloon.paMemObj[i] == NIL_RTR0MEMOBJ)
     523            pMemObj = &pDevExt->MemBalloon.paMemObj[i]; /* found free object pointer */
     524        if (RTR0MemObjAddressR3(pDevExt->MemBalloon.paMemObj[i]) == u64ChunkAddr)
    524525        {
    525526            if (fInflate)
    526527                return VERR_ALREADY_EXISTS; /* don't provide the same memory twice */
    527             pMemObj = &pSession->MemBalloon.paMemObj[i];
     528            pMemObj = &pDevExt->MemBalloon.paMemObj[i];
    528529            break;
    529530        }
     
    532533    {
    533534        if (fInflate)
    534             return VERR_NO_MEMORY; /* no free object pointer found -- should not happen */
    535         return VERR_NOT_FOUND; /* cannot free this memory as it wasn't provided before */
     535        {
     536            /* no free object pointer found -- should not happen */
     537            return VERR_NO_MEMORY;
     538        }
     539
     540        /* cannot free this memory as it wasn't provided before */
     541        return VERR_NOT_FOUND;
    536542    }
    537543
     
    548554            rc = vboxGuestBalloonInflate(pMemObj, pReq);
    549555            if (RT_SUCCESS(rc))
    550                 pSession->MemBalloon.cChunks++;
     556                pDevExt->MemBalloon.cChunks++;
    551557            else
    552558            {
     
    561567        rc = vboxGuestBalloonDeflate(pMemObj, pReq);
    562568        if (RT_SUCCESS(rc))
    563             pSession->MemBalloon.cChunks--;
     569            pDevExt->MemBalloon.cChunks--;
    564570        else
    565571            Log(("vboxGuestSetBalloonSize(deflate): failed, rc=%Rrc!\n", rc));
     
    573579/**
    574580 * Cleanup the memory balloon of a session.
    575  */
    576 static void vboxGuestCloseSessionMemBalloon(PVBOXGUESTSESSION pSession)
    577 {
    578     if (pSession->MemBalloon.paMemObj)
     581 *
     582 * @param   pDevExt     The device extension.
     583 * @param   pDevExt     The session. Can be NULL if no owner check required.
     584 */
     585static void vboxGuestCloseMemBalloon(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession)
     586{
     587    if (   pSession != (PVBOXGUESTSESSION)NULL
     588        && ASMAtomicReadPtr((void * volatile *)&pDevExt->MemBalloon.pOwner) != pSession)
     589        return;
     590
     591    if (pDevExt->MemBalloon.paMemObj)
    579592    {
    580593        VMMDevChangeMemBalloon *pReq;
     
    583596        {
    584597            uint32_t i;
    585             for (i = pSession->MemBalloon.cChunks; i-- > 0;)
     598            for (i = pDevExt->MemBalloon.cChunks; i-- > 0;)
    586599            {
    587                 rc = vboxGuestBalloonDeflate(&pSession->MemBalloon.paMemObj[i], pReq);
     600                rc = vboxGuestBalloonDeflate(&pDevExt->MemBalloon.paMemObj[i], pReq);
    588601                if (RT_FAILURE(rc))
    589602                {
     
    591604                    break;
    592605                }
    593                 pSession->MemBalloon.paMemObj[i] = NIL_RTR0MEMOBJ;
    594                 pSession->MemBalloon.cChunks--;
     606                pDevExt->MemBalloon.paMemObj[i] = NIL_RTR0MEMOBJ;
     607                pDevExt->MemBalloon.cChunks--;
    595608            }
    596609            VbglGRFree(&pReq->header);
    597610        }
    598         RTMemFree(pSession->MemBalloon.paMemObj);
    599         pSession->MemBalloon.paMemObj = NULL;
    600     }
    601 }
    602 
    603 
    604 /**
    605  * Init the variables for memory ballooning
     611        RTMemFree(pDevExt->MemBalloon.paMemObj);
     612        pDevExt->MemBalloon.paMemObj = NULL;
     613    }
     614
     615    ASMAtomicWritePtr((void * volatile *)&pDevExt->MemBalloon.pOwner, NULL);
     616}
     617
     618
     619/**
     620 * Init the variables for memory ballooning.
    606621 *
    607622 * @param   pDevExt     The device extension
     
    613628    pDevExt->MemBalloon.fUseKernelAPI = true;
    614629    pDevExt->MemBalloon.paMemObj = NULL;
    615 }
    616 
    617 
    618 /**
    619  * Finish memory ballooning, reclaim all memory from the host.
    620  *
    621  * @param   pDevExt     The device extension
    622  */
    623 static void vboxGuestDoneMemBalloon(PVBOXGUESTDEVEXT pDevExt)
    624 {
    625     if (pDevExt->MemBalloon.paMemObj)
    626     {
    627         vboxGuestSetBalloonSizeKernel(pDevExt, 0);
    628         RTMemFree(pDevExt->MemBalloon.paMemObj);
    629         pDevExt->MemBalloon.paMemObj = NULL;
    630     }
     630    ASMAtomicWritePtr((void * volatile *)&pDevExt->MemBalloon.pOwner, NULL);
    631631}
    632632
     
    822822    VBoxGuestSetGuestCapabilities(0, UINT32_MAX);
    823823    vboxGuestSetFilterMask(pDevExt, 0);
    824     vboxGuestDoneMemBalloon(pDevExt);
     824    vboxGuestCloseMemBalloon(pDevExt, (PVBOXGUESTSESSION)NULL);
    825825
    826826    /*
     
    867867    pSession->R0Process = RTR0ProcHandleSelf();
    868868    pSession->pDevExt = pDevExt;
    869 
    870     pSession->MemBalloon.cChunks = 0;
    871     pSession->MemBalloon.cMaxChunks = 0;
    872869
    873870    *ppSession = pSession;
     
    937934    pSession->Process = NIL_RTPROCESS;
    938935    pSession->R0Process = NIL_RTR0PROCESS;
    939     vboxGuestCloseSessionMemBalloon(pSession);
     936    vboxGuestCloseMemBalloon(pDevExt, pSession);
    940937    RTMemFree(pSession);
    941938}
     
    18451842 *
    18461843 * @param   pDevExt             The device extension.
     1844 * @param   pSession            The session.
    18471845 * @param   pInfo               The output buffer.
    18481846 * @param   pcbDataReturned     Where to store the amount of returned data. Can
    18491847 *                              be NULL.
    18501848 */
    1851 static int VBoxGuestCommonIOCtl_QueryMemoryBalloon(PVBOXGUESTDEVEXT pDevExt,
     1849static int VBoxGuestCommonIOCtl_QueryMemoryBalloon(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
    18521850                                                   VBoxGuestCheckBalloonInfo *pInfo, size_t *pcbDataReturned)
    18531851{
    18541852    VMMDevGetMemBalloonChangeRequest *pReq;
     1853    PVBOXGUESTSESSION pOwner;
     1854    int rc;
     1855
    18551856    Log(("VBoxGuestCommonIOCtl: QUERYMEMORYBALLOON\n"));
    1856     int rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(VMMDevGetMemBalloonChangeRequest), VMMDevReq_GetMemBalloonChangeRequest);
     1857    /* the first user trying to query/change the balloon is the owner */
     1858    if (   !ASMAtomicCmpXchgExPtr((void * volatile *)&pDevExt->MemBalloon.pOwner, (const void*) pSession,
     1859                                   (PVBOXGUESTSESSION)NULL, (void**)&pOwner)
     1860        && pOwner != pSession)
     1861        return VERR_PERMISSION_DENIED;
     1862
     1863    rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(VMMDevGetMemBalloonChangeRequest), VMMDevReq_GetMemBalloonChangeRequest);
    18571864    if (RT_FAILURE(rc))
    18581865        return rc;
    1859 
    1860 /** @todo r=bird: The following needs to be serialized as there is no one
    1861  *        saying mr. evil user cannot start more than one VBoxService. */
    18621866
    18631867    /* This is a response to that event. Setting this bit means that we request the value
     
    18751879    pDevExt->MemBalloon.cMaxChunks = pReq->cPhysMemChunks;
    18761880
    1877     rc = vboxGuestSetBalloonSizeKernel(pDevExt, pReq->cBalloonChunks);
     1881    rc = vboxGuestSetBalloonSizeKernel(pDevExt, pSession, pReq->cBalloonChunks);
    18781882    /* Ignore out of memory failures */
    18791883    if (rc == VERR_NO_MEMORY)
     
    18881892        rc = VINF_SUCCESS;
    18891893    }
     1894
     1895    VbglGRFree(&pReq->header);
    18901896
    18911897    if (pcbDataReturned)
     
    19111917                                                    VBoxGuestChangeBalloonInfo *pInfo, size_t *pcbDataReturned)
    19121918{
    1913 /** @todo r=bird: Don't allow this if fUseKernelAPI is true.  */
    1914 /** @todo r=bird: This needs to be serialized as there is no one saying mr. evil
    1915  *        user cannot start more than one VBoxService.
    1916  *
    1917  *        Actually, it would be good to drop the VBOXGUESTSESSION::MemBalloon
    1918  *        and instead add a VBOXGUESTDEVEXT::pMemBallonOwner
    1919  *        (PVBOXGUESTSESSION).  Assign balloon ownership on a first come
    1920  *        basis, releasing it when the session quits.  This could be done
    1921  *        regardless of the method use for memory allocation. */
    1922     int rc = vboxGuestSetBalloonSizeFromUser(pDevExt, pSession, pInfo->u64ChunkAddr, pInfo->fInflate);
     1919    int rc;
     1920    PVBOXGUESTSESSION pOwner;
     1921
     1922    if (pDevExt->MemBalloon.fUseKernelAPI)
     1923        return VERR_PERMISSION_DENIED;
     1924
     1925    /* the first user trying to query/change the balloon is the owner */
     1926    if (   !ASMAtomicCmpXchgExPtr((void * volatile *)&pDevExt->MemBalloon.pOwner, (const void*) pSession,
     1927                                   (PVBOXGUESTSESSION)NULL, (void**)&pOwner)
     1928        && pOwner != pSession)
     1929        return VERR_PERMISSION_DENIED;
     1930
     1931    rc = vboxGuestSetBalloonSizeFromUser(pDevExt, pSession, pInfo->u64ChunkAddr, pInfo->fInflate);
    19231932    if (pcbDataReturned)
    19241933        *pcbDataReturned = 0;
     
    21092118            case VBOXGUEST_IOCTL_CHECK_BALLOON:
    21102119                CHECKRET_MIN_SIZE("CHECK_MEMORY_BALLOON", sizeof(VBoxGuestCheckBalloonInfo));
    2111                 rc = VBoxGuestCommonIOCtl_QueryMemoryBalloon(pDevExt, (VBoxGuestCheckBalloonInfo *)pvData, pcbDataReturned);
     2120                rc = VBoxGuestCommonIOCtl_QueryMemoryBalloon(pDevExt, pSession, (VBoxGuestCheckBalloonInfo *)pvData, pcbDataReturned);
    21122121                break;
    21132122
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuestInternal.h

    r27106 r27118  
    9090     * and false otherwise. */
    9191    bool                        fUseKernelAPI;
     92    /** The owner of the balloon which is the first process using the balloon API. */
     93    PVBOXGUESTSESSION volatile  pOwner;
    9294    /** The pointer to the array of memory objects holding the chunks of the
    9395     *  balloon.  This array is cMaxChunks in size when present. */
     
    186188    uint32_t volatile           u32MousePosChangedSeq;
    187189
    188     /* Memory ballooning information if userland provides the balloon memory. */
    189     VBOXGUESTMEMBALLOON         MemBalloon;
    190190} VBOXGUESTSESSION;
    191191
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