VirtualBox

Ignore:
Timestamp:
Nov 15, 2018 5:24:47 AM (6 years ago)
Author:
vboxsync
Message:
  1. Serialized VDRead()/VDWrite calls. 2. Fixed borrowed write align code to properly ret. # bytes written. Mount more reliable now.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ImageMounter/vboxraw/vboxraw.cpp

    r75266 r75475  
    2121*********************************************************************************************************************************/
    2222#define LOG_GROUP LOG_GROUP_DEFAULT /** @todo log group */
    23 #define UNUSED(x) (void)(x)
    2423
    2524#define FUSE_USE_VERSION 27
     
    4948#include <VBox/com/VirtualBox.h>
    5049#include <VBox/vd.h>
     50#include <VBox/vd-ifs.h>
    5151#include <VBox/log.h>
    5252#include <VBox/err.h>
     
    6060
    6161#include <iprt/initterm.h>
    62 #include <iprt/critsect.h>
    6362#include <iprt/assert.h>
    6463#include <iprt/message.h>
     64#include <iprt/critsect.h>
    6565#include <iprt/asm.h>
    6666#include <iprt/mem.h>
     
    7171#include <iprt/path.h>
    7272
     73#pragma GCC diagnostic ignored "-Wunused-variable"
     74#pragma GCC diagnostic ignored "-Wunused-parameter"
     75#pragma GCC diagnostic ignored "-Wunused-function"
     76
    7377using namespace com;
    7478
     
    8589
    8690
    87 /** The VDRead/VDWrite block granularity. */
    88 #define VBoxRAW_MIN_SIZE               512
    89 /** Offset mask corresponding to VBoxRAW_MIN_SIZE. */
    90 #define VBoxRAW_MIN_SIZE_MASK_OFF      (0x1ff)
    91 /** Block mask corresponding to VBoxRAW_MIN_SIZE. */
    92 #define VBoxRAW_MIN_SIZE_MASK_BLK      (~UINT64_C(0x1ff))
    93 
    94 #define PADMAX                      50
    95 #define MAX_ID_LEN                  256
    96 #define CSTR(arg) Utf8Str(arg).c_str()
     91#define VD_SECTOR_SIZE                   0x200 /* 0t512 */
     92#define VD_SECTOR_MASK                   (VD_SECTOR_SIZE - 1)
     93#define VD_SECTOR_OUT_OF_BOUNDS_MASK     (~UINT64_C(VD_SECTOR_MASK))
     94
     95#define PADMAX                           50
     96#define MAX_ID_LEN                       256
     97#define CSTR(arg)                        Utf8Str(arg).c_str()
    9798
    9899static struct fuse_operations   g_vboxrawOps;
    99 PVDISK      g_pVDisk;
    100 int32_t     g_cReaders;
    101 int32_t     g_cWriters;
    102 RTFOFF      g_cbPrimary;
    103 char        *g_pszBaseImageName;
    104 char        *g_pszBaseImagePath;
     100PVDISK                g_pVDisk;
     101int32_t               g_cReaders;
     102int32_t               g_cWriters;
     103RTFOFF                g_cbPrimary;
     104char                 *g_pszBaseImageName;
     105char                 *g_pszBaseImagePath;
     106PVDINTERFACE          g_pVdIfs;             /** @todo Remove when VD I/O becomes threadsafe */
     107VDINTERFACETHREADSYNC g_VDIfThreadSync;     /** @todo Remove when VD I/O becomes threadsafe */
     108RTCRITSECT            g_vdioLock;           /** @todo Remove when VD I/O becomes threadsafe */
    105109
    106110char *nsIDToString(nsID *guid);
     
    109113
    110114static struct vboxrawOpts {
    111      char *pszVm;
    112      char *pszImage;
    113      char *pszImageUuid;
     115     char    *pszVm;
     116     char    *pszImage;
     117     char    *pszImageUuid;
    114118     uint32_t cHddImageDiffMax;
    115119     uint32_t fList;
     
    235239}
    236240
     241/** @todo Remove when VD I/O becomes threadsafe */
     242static DECLCALLBACK(int) vboxrawThreadStartRead(void *pvUser)
     243{
     244    PRTCRITSECT vdioLock = (PRTCRITSECT)pvUser;
     245    return RTCritSectEnter(vdioLock);
     246}
     247
     248static DECLCALLBACK(int) vboxrawThreadFinishRead(void *pvUser)
     249{
     250    PRTCRITSECT vdioLock = (PRTCRITSECT)pvUser;
     251    return RTCritSectLeave(vdioLock);
     252}
     253
     254static DECLCALLBACK(int) vboxrawThreadStartWrite(void *pvUser)
     255{
     256    PRTCRITSECT vdioLock = (PRTCRITSECT)pvUser;
     257    return RTCritSectEnter(vdioLock);
     258}
     259
     260static DECLCALLBACK(int) vboxrawThreadFinishWrite(void *pvUser)
     261{
     262    PRTCRITSECT vdioLock = (PRTCRITSECT)pvUser;
     263    return RTCritSectLeave(vdioLock);
     264}
     265
     266/** @todo (end of to do section) */
     267
    237268/** @copydoc fuse_operations::release */
    238269static int vboxrawOp_release(const char *pszPath, struct fuse_file_info *pInfo)
     
    260291}
    261292
    262 static int retryableVDRead(PVDISK pvDisk, uint64_t offset, void *pvBuf, size_t cbRead)
    263 {
    264     int rc = -1;
    265     int cRetry = 5;
    266     do
    267     {
    268         if (cRetry < 5)
    269             Log(("(rc=%d retrying read)\n", rc));
    270         rc = VDRead(pvDisk, offset, pvBuf, cbRead);
    271     } while (RT_FAILURE(rc) && --cRetry);
    272     return rc;
    273 }
     293
     294/**
     295 * VD read Sanitizer taking care of unaligned accesses.
     296 *
     297 * @return  VBox status code.
     298 * @param   pDisk    VD disk container.
     299 * @param   off      Offset to start reading from.
     300 * @param   pvBuf    Pointer to the buffer to read into.
     301 * @param   cbRead   Amount of bytes to read.
     302 */
     303static int vdReadSanitizer(PVDISK pDisk, uint64_t off, void *pvBuf, size_t cbRead)
     304{
     305    int rc;
     306
     307    uint64_t const cbMisalignHead = off & VD_SECTOR_MASK;
     308    uint64_t const cbcbMisalignTail  = (off + cbRead) & VD_SECTOR_MASK;
     309
     310    if (cbMisalignHead + cbcbMisalignTail == 0) /* perfectly aligned request; just read it and done */
     311        rc = VDRead(pDisk, off, pvBuf, cbRead);
     312    else
     313    {
     314        uint8_t *pbBuf = (uint8_t *)pvBuf;
     315        uint8_t abBuf[VD_SECTOR_SIZE];
     316
     317        /* If offset not @ sector boundary, read whole sector, then copy unaligned
     318         * bytes (requested by user), only up to sector boundary, into user's buffer
     319         */
     320        if (cbMisalignHead)
     321        {
     322            rc = VDRead(pDisk, off - cbMisalignHead, abBuf, VD_SECTOR_SIZE);
     323            if (RT_SUCCESS(rc))
     324            {
     325                size_t const cbPart = RT_MIN(VD_SECTOR_SIZE - cbMisalignHead, cbRead);
     326                memcpy(pbBuf, &abBuf[cbMisalignHead], cbPart);
     327                pbBuf  += cbPart;
     328                off    += cbPart; /* Beginning of next sector or EOD */
     329                cbRead -= cbPart; /* # left to read */
     330            }
     331        }
     332        else /* user's offset already aligned, did nothing */
     333            rc = VINF_SUCCESS;
     334
     335        /* Read remaining aligned sectors, deferring any tail-skewed bytes */
     336        if (RT_SUCCESS(rc) && cbRead >= VD_SECTOR_SIZE)
     337        {
     338            Assert(!(off % VD_SECTOR_SIZE));
     339
     340            size_t cbPart = cbRead - cbcbMisalignTail;
     341            Assert(!(cbPart % VD_SECTOR_SIZE));
     342            rc = VDRead(pDisk, off, pbBuf, cbPart);
     343            if (RT_SUCCESS(rc))
     344            {
     345                pbBuf  += cbPart;
     346                off    += cbPart;
     347                cbRead -= cbPart;
     348            }
     349        }
     350
     351        /* Unaligned buffered read of tail. */
     352        if (RT_SUCCESS(rc) && cbRead)
     353        {
     354            Assert(cbRead == cbcbMisalignTail);
     355            Assert(cbRead < VD_SECTOR_SIZE);
     356            Assert(!(off % VD_SECTOR_SIZE));
     357
     358            rc = VDRead(pDisk, off, abBuf, VD_SECTOR_SIZE);
     359            if (RT_SUCCESS(rc))
     360                memcpy(pbBuf, abBuf, cbRead);
     361        }
     362    }
     363
     364    if (RT_FAILURE(rc))
     365    {
     366        int sysrc = -RTErrConvertToErrno(rc);
     367        LogFlowFunc(("error: %s (vbox err: %d)\n", strerror(sysrc), rc));
     368        rc = sysrc;
     369    }
     370    return cbRead;
     371}
     372
     373/**
     374 * VD write Sanitizer taking care of unaligned accesses.
     375 *
     376 * @return  VBox status code.
     377 * @param   pDisk    VD disk container.
     378 * @param   off      Offset to start writing to.
     379 * @param   pvSrc    Pointer to the buffer to read from.
     380 * @param   cbWrite  Amount of bytes to write.
     381 */
     382static int vdWriteSanitizer(PVDISK pDisk, uint64_t off, const void *pvSrc, size_t cbWrite)
     383{
     384    uint8_t const *pbSrc = (uint8_t const *)pvSrc;
     385    uint8_t        abBuf[4096];
     386    int rc;
     387    int cbRemaining = cbWrite;
     388    /*
     389     * Take direct route if the request is sector aligned.
     390     */
     391    uint64_t const cbMisalignHead = off & 511;
     392    size_t   const cbcbMisalignTail  = (off + cbWrite) & 511;
     393    if (!cbMisalignHead && !cbcbMisalignTail)
     394    {
     395          rc = VDWrite(pDisk, off, pbSrc, cbWrite);
     396          do
     397            {
     398                size_t cbThisWrite = RT_MIN(cbWrite, sizeof(abBuf));
     399                rc = VDWrite(pDisk, off, memcpy(abBuf, pbSrc, cbThisWrite), cbThisWrite);
     400                if (RT_SUCCESS(rc))
     401                {
     402                    pbSrc   += cbThisWrite;
     403                    off     += cbThisWrite;
     404                    cbRemaining -= cbThisWrite;
     405                }
     406                else
     407                    break;
     408            } while (cbRemaining > 0);
     409    }
     410    else
     411    {
     412        /*
     413         * Unaligned buffered read+write of head.  Aligns the offset.
     414         */
     415        if (cbMisalignHead)
     416        {
     417            rc = VDRead(pDisk, off - cbMisalignHead, abBuf, VD_SECTOR_SIZE);
     418            if (RT_SUCCESS(rc))
     419            {
     420                size_t const cbPart = RT_MIN(VD_SECTOR_SIZE - cbMisalignHead, cbWrite);
     421                memcpy(&abBuf[cbMisalignHead], pbSrc, cbPart);
     422                rc = VDWrite(pDisk, off - cbMisalignHead, abBuf, VD_SECTOR_SIZE);
     423                if (RT_SUCCESS(rc))
     424                {
     425                    pbSrc   += cbPart;
     426                    off     += cbPart;
     427                    cbRemaining -= cbPart;
     428                }
     429            }
     430        }
     431        else
     432            rc = VINF_SUCCESS;
     433
     434        /*
     435         * Aligned direct write.
     436         */
     437        if (RT_SUCCESS(rc) && cbWrite >= VD_SECTOR_SIZE)
     438        {
     439            Assert(!(off % VD_SECTOR_SIZE));
     440            size_t cbPart = cbWrite - cbcbMisalignTail;
     441            Assert(!(cbPart % VD_SECTOR_SIZE));
     442            rc = VDWrite(pDisk, off, pbSrc, cbPart);
     443            if (RT_SUCCESS(rc))
     444            {
     445                pbSrc   += cbPart;
     446                off     += cbPart;
     447                cbRemaining -= cbPart;
     448            }
     449        }
     450
     451        /*
     452         * Unaligned buffered read + write of tail.
     453         */
     454        if (   RT_SUCCESS(rc) && cbWrite > 0)
     455        {
     456            Assert(cbWrite == cbcbMisalignTail);
     457            Assert(cbWrite < VD_SECTOR_SIZE);
     458            Assert(!(off % VD_SECTOR_SIZE));
     459            rc = VDRead(pDisk, off, abBuf, VD_SECTOR_SIZE);
     460            if (RT_SUCCESS(rc))
     461            {
     462                memcpy(abBuf, pbSrc, cbWrite);
     463                rc = VDWrite(pDisk, off, abBuf, VD_SECTOR_SIZE);
     464            }
     465        }
     466    }
     467    if (RT_FAILURE(rc))
     468    {
     469        int sysrc = -RTErrConvertToErrno(rc);
     470        LogFlowFunc(("error: %s (vbox err: %d)\n", strerror(sysrc), rc));
     471        return sysrc;
     472    }
     473    return cbWrite - cbRemaining;
     474}
     475
    274476
    275477/** @copydoc fuse_operations::read */
     
    277479                           off_t offset, struct fuse_file_info *pInfo)
    278480{
    279 
    280481    (void) pszPath;
    281482    (void) pInfo;
     
    283484    LogFlowFunc(("my offset=%#llx size=%#zx path=\"%s\"\n", (uint64_t)offset, cbBuf, pszPath));
    284485
    285     /* paranoia */
     486    AssertReturn(offset >= 0, -EINVAL);
    286487    AssertReturn((int)cbBuf >= 0, -EINVAL);
    287488    AssertReturn((unsigned)cbBuf == cbBuf, -EINVAL);
    288     AssertReturn(offset >= 0, -EINVAL);
    289     AssertReturn((off_t)(offset + cbBuf) >= offset, -EINVAL);
    290 
    291     int rc;
     489
     490    int rc = 0;
    292491    if ((off_t)(offset + cbBuf) < offset)
    293492        rc = -EINVAL;
    294493    else if (offset >= g_cbPrimary)
    295         rc = 0;
     494        return 0;
    296495    else if (!cbBuf)
    297         rc = 0;
    298     else
    299     {
    300         /* Adjust for EOF. */
    301         if ((off_t)(offset + cbBuf) >= g_cbPrimary)
    302             cbBuf = g_cbPrimary - offset;
    303 
    304         /*
    305          * Aligned read?
    306          */
    307         int rc2;
    308         if (    !(offset & VBoxRAW_MIN_SIZE_MASK_OFF)
    309             &&  !(cbBuf   & VBoxRAW_MIN_SIZE_MASK_OFF))
    310         {
    311                 rc2 = retryableVDRead(g_pVDisk, offset, pbBuf, cbBuf);
    312                 if (RT_FAILURE(rc2))
    313                 {
    314                     rc = -RTErrConvertToErrno(rc2);
    315                     LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
    316                     return rc;
    317                 }
    318         }
    319         else
    320         {
    321             /*
    322              * Unaligned read - lots of extra work.
    323              */
    324             uint8_t abBlock[VBoxRAW_MIN_SIZE];
    325             if (((offset + cbBuf) & VBoxRAW_MIN_SIZE_MASK_BLK) == (offset & VBoxRAW_MIN_SIZE_MASK_BLK))
    326             {
    327                 /* a single partial block. */
    328                 rc2 = retryableVDRead(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE);
    329                 if (RT_SUCCESS(rc2))
    330                 {
    331                     memcpy(pbBuf, &abBlock[offset & VBoxRAW_MIN_SIZE_MASK_OFF], cbBuf);
    332                 }
    333                 else
    334                 {
    335                     rc = -RTErrConvertToErrno(rc2);
    336                     LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
    337                     return rc;
    338                 }
    339             }
    340             else
    341             {
    342                 /* read unaligned head. */
    343                 rc2 = VINF_SUCCESS;
    344                 if (offset & VBoxRAW_MIN_SIZE_MASK_OFF)
    345                 {
    346                     rc2 = retryableVDRead(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE);
    347                     if (RT_SUCCESS(rc2))
    348                     {
    349                         size_t cbCopy = VBoxRAW_MIN_SIZE - (offset & VBoxRAW_MIN_SIZE_MASK_OFF);
    350                         memcpy(pbBuf, &abBlock[offset & VBoxRAW_MIN_SIZE_MASK_OFF], cbCopy);
    351                         pbBuf   += cbCopy;
    352                         offset += cbCopy;
    353                         cbBuf   -= cbCopy;
    354                     }
    355                     else
    356                     {
    357                         rc = -RTErrConvertToErrno(rc2);
    358                         LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
    359                         return rc;
    360                     }
    361                 }
    362 
    363                 /* read the middle. */
    364                 Assert(!(offset & VBoxRAW_MIN_SIZE_MASK_OFF));
    365                 if (cbBuf >= VBoxRAW_MIN_SIZE && RT_SUCCESS(rc2))
    366                 {
    367                     size_t cbRead = cbBuf & VBoxRAW_MIN_SIZE_MASK_BLK;
    368                     rc2 = retryableVDRead(g_pVDisk, offset, pbBuf, cbRead);
    369                     if (RT_SUCCESS(rc2))
    370                     {
    371                         pbBuf   += cbRead;
    372                         offset += cbRead;
    373                         cbBuf   -= cbRead;
    374                     }
    375                     else
    376                     {
    377                         rc = -RTErrConvertToErrno(rc2);
    378                         LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
    379                         return rc;
    380                     }
    381                 }
    382 
    383                 /* unaligned tail read. */
    384                 Assert(cbBuf < VBoxRAW_MIN_SIZE);
    385                 Assert(!(offset & VBoxRAW_MIN_SIZE_MASK_OFF));
    386                 if (cbBuf && RT_SUCCESS(rc2))
    387                 {
    388                     rc2 = retryableVDRead(g_pVDisk, offset, abBlock, VBoxRAW_MIN_SIZE);
    389                     if (RT_SUCCESS(rc2)) {
    390                         memcpy(pbBuf, &abBlock[0], cbBuf);
    391                     }
    392                     else
    393                     {
    394                         rc = -RTErrConvertToErrno(rc2);
    395                         LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
    396                         return rc;
    397                     }
    398                 }
    399             }
    400         }
    401 
    402         /* convert the return code */
    403         if (RT_SUCCESS(rc2))
    404             rc = cbBuf;
    405         else
    406         {
    407             rc = -RTErrConvertToErrno(rc2);
    408             LogFlowFunc(("Error rc2=%d, rc=%d=%s\n", rc2, rc, strerror(rc)));
    409         }
    410         return rc;
    411     }
     496        return 0;
     497
     498    if (rc >= 0)
     499        rc = vdReadSanitizer(g_pVDisk, offset, pbBuf, cbBuf);
     500    if (rc < 0)
     501        LogFlowFunc(("%s\n", strerror(rc)));
    412502    return rc;
    413503}
    414504
    415 /** @copydoc fuse_operations::write */
     505/** @ fuse_operations::write */
    416506static int vboxrawOp_write(const char *pszPath, const char *pbBuf, size_t cbBuf,
    417507                           off_t offset, struct fuse_file_info *pInfo)
    418508{
    419 
    420509    (void) pszPath;
    421510    (void) pInfo;
    422511
    423 
     512    LogFlowFunc(("offset=%#llx size=%#zx path=\"%s\"\n", (uint64_t)offset, cbBuf, pszPath));
     513
     514    AssertReturn(offset >= 0, -EINVAL);
    424515    AssertReturn((int)cbBuf >= 0, -EINVAL);
    425516    AssertReturn((unsigned)cbBuf == cbBuf, -EINVAL);
    426     AssertReturn(offset >= 0, -EINVAL);
    427     AssertReturn((off_t)(offset + cbBuf) >= offset, -EINVAL);
    428 
    429 
    430     LogFlowFunc(("offset=%#llx size=%#zx path=\"%s\"\n", (uint64_t)offset, cbBuf, pszPath));
    431 
    432     int rc;
    433     if (!g_vboxrawOpts.fRW)
    434         rc = -EPERM;
    435     else if ((off_t)(offset + cbBuf) < offset)
     517
     518    int rc = 0;
     519    if (!g_vboxrawOpts.fRW) {
     520        LogFlowFunc(("WARNING: vboxraw (FUSE FS) --rw option not specified\n"
     521                     "              (write operation ignored w/o error!)\n"));
     522        return cbBuf;
     523    } else if ((off_t)(offset + cbBuf) < offset)
    436524        rc = -EINVAL;
    437525    else if (offset >= g_cbPrimary)
    438         rc = 0;
     526        return 0;
    439527    else if (!cbBuf)
    440         rc = 0;
    441     else
    442     {
    443         /* Adjust for EOF. */
    444         if ((off_t)(offset + cbBuf) >= g_cbPrimary)
    445             cbBuf = g_cbPrimary - offset;
    446 
    447         /*
    448          * Aligned write?
    449          */
    450         int rc2;
    451         if (    !(offset & VBoxRAW_MIN_SIZE_MASK_OFF)
    452             &&  !(cbBuf   & VBoxRAW_MIN_SIZE_MASK_OFF))
    453         {
    454                 rc2 = VDWrite(g_pVDisk, offset, pbBuf, cbBuf);
    455                 if (RT_FAILURE(rc2))
    456                 {
    457                     rc = -RTErrConvertToErrno(rc2);
    458                     LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
    459                     return rc;
    460                 }
    461         }
    462         else
    463         {
    464             /*
    465              * Unaligned write - lots of extra work.
    466              */
    467             uint8_t abBlock[VBoxRAW_MIN_SIZE];
    468             if (((offset + cbBuf) & VBoxRAW_MIN_SIZE_MASK_BLK) == (offset & VBoxRAW_MIN_SIZE_MASK_BLK))
    469             {
    470                 /* a single partial block. */
    471                 rc2 = VDRead(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE);
    472                 if (RT_SUCCESS(rc2))
    473                 {
    474                     memcpy(&abBlock[offset & VBoxRAW_MIN_SIZE_MASK_OFF], pbBuf, cbBuf);
    475                     /* Update the block */
    476                     rc2 = VDWrite(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE);
    477                     if (RT_FAILURE(rc2))
    478                     {
    479                         rc = -RTErrConvertToErrno(rc2);
    480                         LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
    481                         return rc;
    482                     }
    483                 }
    484                 else
    485                 {
    486                     rc = -RTErrConvertToErrno(rc2);
    487                     LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
    488                     return rc;
    489                 }
    490             }
    491             else
    492             {
    493                 /* read unaligned head. */
    494                 rc2 = VINF_SUCCESS;
    495                 if (offset & VBoxRAW_MIN_SIZE_MASK_OFF)
    496                 {
    497                     rc2 = VDRead(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE);
    498                     if (RT_SUCCESS(rc2))
    499                     {
    500                         size_t cbCopy = VBoxRAW_MIN_SIZE - (offset & VBoxRAW_MIN_SIZE_MASK_OFF);
    501                         memcpy(&abBlock[offset & VBoxRAW_MIN_SIZE_MASK_OFF], pbBuf, cbCopy);
    502                         pbBuf   += cbCopy;
    503                         offset += cbCopy;
    504                         cbBuf   -= cbCopy;
    505                         rc2 = VDWrite(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE);
    506                         if (RT_FAILURE(rc2))
    507                         {
    508                             rc = -RTErrConvertToErrno(rc2);
    509                             LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
    510                             return rc;
    511                         }
    512                     }
    513                     else
    514                     {
    515                         rc = -RTErrConvertToErrno(rc2);
    516                         LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
    517                         return rc;
    518                     }
    519                 }
    520 
    521                 /* write the middle. */
    522                 Assert(!(offset & VBoxRAW_MIN_SIZE_MASK_OFF));
    523                 if (cbBuf >= VBoxRAW_MIN_SIZE && RT_SUCCESS(rc2))
    524                 {
    525                     size_t cbWrite = cbBuf & VBoxRAW_MIN_SIZE_MASK_BLK;
    526                     rc2 = VDWrite(g_pVDisk, offset, pbBuf, cbWrite);
    527                     if (RT_SUCCESS(rc2))
    528                     {
    529                         pbBuf   += cbWrite;
    530                         offset += cbWrite;
    531                         cbBuf   -= cbWrite;
    532                     }
    533                     if (RT_FAILURE(rc2))
    534                     {
    535                         rc = -RTErrConvertToErrno(rc2);
    536                         LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
    537                         return rc;
    538                     }
    539                 }
    540 
    541                 /* unaligned tail write. */
    542                 Assert(cbBuf < VBoxRAW_MIN_SIZE);
    543                 Assert(!(offset & VBoxRAW_MIN_SIZE_MASK_OFF));
    544                 if (cbBuf && RT_SUCCESS(rc2))
    545                 {
    546                     rc2 = VDRead(g_pVDisk, offset, abBlock, VBoxRAW_MIN_SIZE);
    547                     if (RT_SUCCESS(rc2))
    548                     {
    549                         memcpy(&abBlock[0], pbBuf, cbBuf);
    550                         rc2 = VDWrite(g_pVDisk, offset, abBlock, VBoxRAW_MIN_SIZE);
    551                         if (RT_FAILURE(rc2))
    552                         {
    553                             rc = -RTErrConvertToErrno(rc2);
    554                             LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
    555                             return rc;
    556                         }
    557                     }
    558                     else
    559                     {
    560                         rc = -RTErrConvertToErrno(rc2);
    561                         LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
    562                         return rc;
    563                     }
    564                 }
    565             }
    566         }
    567 
    568         /* convert the return code */
    569         if (RT_SUCCESS(rc2))
    570             rc = cbBuf;
    571         else
    572         {
    573             rc = -RTErrConvertToErrno(rc2);
    574             LogFlowFunc(("Error rc2=%d, rc=%d=%s\n", rc2, rc, strerror(rc)));
    575             return rc;
    576         }
    577     }
     528        return 0;
     529
     530    if (rc >= 0)
     531        rc = vdWriteSanitizer(g_pVDisk, offset, pbBuf, cbBuf);
     532    if (rc < 0)
     533        LogFlowFunc(("%s\n", strerror(rc)));
     534
    578535    return rc;
    579536}
     
    994951                if (g_vboxrawOpts.fVerbose)
    995952                    RTPrintf("vboxraw: Creating container for base image of format %s\n", pszFormat);
     953                /** @todo Remove I/O CB's and crit sect. when VDRead()/VDWrite() are made threadsafe */
     954                rc = RTCritSectInit(&g_vdioLock);
     955                if (RT_SUCCESS(rc))
     956                {
     957                    g_VDIfThreadSync.pfnStartRead   = vboxrawThreadStartRead;
     958                    g_VDIfThreadSync.pfnFinishRead  = vboxrawThreadFinishRead;
     959                    g_VDIfThreadSync.pfnStartWrite  = vboxrawThreadStartWrite;
     960                    g_VDIfThreadSync.pfnFinishWrite = vboxrawThreadFinishWrite;
     961                    rc = VDInterfaceAdd(&g_VDIfThreadSync.Core, "vboxraw_ThreadSync", VDINTERFACETYPE_THREADSYNC,
     962                                        &g_vdioLock, sizeof(VDINTERFACETHREADSYNC), &g_pVdIfs);
     963                }
     964                else
     965                    return RTMsgErrorExitFailure("vboxraw: ERROR: Failed to create critsects "
     966                                                 "for virtual disk I/O, rc=%Rrc\n", rc);
    996967
    997968                g_pVDisk = NULL;
    998                 rc = VDCreate(NULL /* pVDIIfsDisk */, enmType, &g_pVDisk);
     969                rc = VDCreate(g_pVdIfs, enmType, &g_pVDisk);
    999970                if (NS_FAILED(rc))
    1000971                    return RTMsgErrorExitFailure("vboxraw: ERROR: Couldn't create virtual disk container\n");
    1001972            }
     973            /** @todo (end of to do section) */
     974
    1002975            if ( g_vboxrawOpts.cHddImageDiffMax != 0 && diffNumber > g_vboxrawOpts.cHddImageDiffMax)
    1003976                break;
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