VirtualBox

Changeset 77853 in vbox


Ignore:
Timestamp:
Mar 22, 2019 8:54:14 PM (6 years ago)
Author:
vboxsync
Message:

linux/vboxsf: Implemented the copy_file_range method and fixed a recently introduced bug in vbsf_reg_write_iter_locking where vbsf_reg_write_sync_page_cache was called with the wrong range length. bugref:9172

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/VBoxGuestLibSharedFoldersInline.h

    r77561 r77853  
    6363extern VBGLSFCLIENT g_SfClient; /**< Move this into the parameters? */
    6464
     65/** Request structure for VbglR0SfHostReqQueryFeatures. */
     66typedef struct VBOXSFQUERYFEATURES
     67{
     68    VBGLIOCIDCHGCMFASTCALL  Hdr;
     69    VMMDevHGCMCall          Call;
     70    VBoxSFParmQueryFeatures Parms;
     71} VBOXSFQUERYFEATURES;
     72
     73/**
     74 * SHFL_FN_QUERY_FEATURES request.
     75 */
     76DECLINLINE(int) VbglR0SfHostReqQueryFeatures(VBOXSFQUERYFEATURES *pReq)
     77{
     78    VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
     79                                SHFL_FN_QUERY_FEATURES, SHFL_CPARMS_QUERY_FEATURES, sizeof(*pReq));
     80
     81    pReq->Parms.f64Features.type          = VMMDevHGCMParmType_64bit;
     82    pReq->Parms.f64Features.u.value64     = 0;
     83
     84    pReq->Parms.u32LastFunction.type      = VMMDevHGCMParmType_32bit;
     85    pReq->Parms.u32LastFunction.u.value32 = 0;
     86
     87    int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, sizeof(*pReq));
     88    if (RT_SUCCESS(vrc))
     89        vrc = pReq->Call.header.result;
     90
     91    /*
     92     * Provide fallback values based on g_fHostFeatures to simplify
     93     * compatibility with older hosts and avoid duplicating this logic.
     94     */
     95    if (RT_FAILURE(vrc))
     96    {
     97        pReq->Parms.f64Features.u.value64     = 0;
     98        pReq->Parms.u32LastFunction.u.value32 = g_fHostFeatures & VMMDEV_HVF_HGCM_NO_BOUNCE_PAGE_LIST
     99                                              ?  SHFL_FN_SET_FILE_SIZE : SHFL_FN_SET_SYMLINKS;
     100        if (vrc == VERR_NOT_SUPPORTED)
     101            vrc = VINF_NOT_SUPPORTED;
     102    }
     103    return vrc;
     104}
     105
     106
     107/**
     108 * SHFL_FN_QUERY_FEATURES request, simplified version.
     109 */
     110DECLINLINE(int) VbglR0SfHostReqQueryFeaturesSimple(uint64_t *pfFeatures, uint32_t *puLastFunction)
     111{
     112    VBOXSFQUERYFEATURES *pReq = (VBOXSFQUERYFEATURES *)VbglR0PhysHeapAlloc(sizeof(*pReq));
     113    if (pReq)
     114    {
     115        int rc = VbglR0SfHostReqQueryFeatures(pReq);
     116        if (pfFeatures)
     117            *pfFeatures = pReq->Parms.f64Features.u.value64;
     118        if (puLastFunction)
     119            *puLastFunction = pReq->Parms.u32LastFunction.u.value32;
     120
     121        VbglR0PhysHeapFree(pReq);
     122        return rc;
     123    }
     124    return VERR_NO_MEMORY;
     125}
     126
     127
     128
    65129/** Request structure for VbglR0SfHostReqMapFolderWithBuf.  */
    66130typedef struct VBOXSFMAPFOLDERWITHBUFREQ
     
    10291093    return vrc;
    10301094}
     1095
     1096
     1097/** Request structure for VbglR0SfHostReqCopyFilePart.  */
     1098typedef struct VBOXSFCOPYFILEPARTREQ
     1099{
     1100    VBGLIOCIDCHGCMFASTCALL  Hdr;
     1101    VMMDevHGCMCall          Call;
     1102    VBoxSFParmCopyFilePart  Parms;
     1103} VBOXSFCOPYFILEPARTREQ;
     1104
     1105/**
     1106 * SHFL_FN_CREATE request.
     1107 */
     1108DECLINLINE(int) VbglR0SfHostReqCopyFilePart(SHFLROOT idRootSrc, SHFLHANDLE hHostFileSrc, uint64_t offSrc,
     1109                                            SHFLROOT idRootDst, SHFLHANDLE hHostFileDst, uint64_t offDst,
     1110                                            uint64_t cbToCopy, uint32_t fFlags, VBOXSFCOPYFILEPARTREQ *pReq)
     1111{
     1112    VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
     1113                                SHFL_FN_COPY_FILE_PART, SHFL_CPARMS_COPY_FILE_PART, sizeof(*pReq));
     1114
     1115    pReq->Parms.id32RootSrc.type        = VMMDevHGCMParmType_32bit;
     1116    pReq->Parms.id32RootSrc.u.value32   = idRootSrc;
     1117
     1118    pReq->Parms.u64HandleSrc.type       = VMMDevHGCMParmType_64bit;
     1119    pReq->Parms.u64HandleSrc.u.value64  = hHostFileSrc;
     1120
     1121    pReq->Parms.off64Src.type           = VMMDevHGCMParmType_64bit;
     1122    pReq->Parms.off64Src.u.value64      = offSrc;
     1123
     1124    pReq->Parms.id32RootDst.type        = VMMDevHGCMParmType_32bit;
     1125    pReq->Parms.id32RootDst.u.value32   = idRootDst;
     1126
     1127    pReq->Parms.u64HandleDst.type       = VMMDevHGCMParmType_64bit;
     1128    pReq->Parms.u64HandleDst.u.value64  = hHostFileDst;
     1129
     1130    pReq->Parms.off64Dst.type           = VMMDevHGCMParmType_64bit;
     1131    pReq->Parms.off64Dst.u.value64      = offDst;
     1132
     1133    pReq->Parms.cb64ToCopy.type         = VMMDevHGCMParmType_64bit;
     1134    pReq->Parms.cb64ToCopy.u.value64    = cbToCopy;
     1135
     1136    pReq->Parms.f32Flags.type           = VMMDevHGCMParmType_32bit;
     1137    pReq->Parms.f32Flags.u.value32      = fFlags;
     1138
     1139    int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, sizeof(*pReq));
     1140    if (RT_SUCCESS(vrc))
     1141        vrc = pReq->Call.header.result;
     1142    return vrc;
     1143}
     1144
     1145
    10311146
    10321147/** Request structure for VbglR0SfHostReqListDirContig2x() and
  • trunk/src/VBox/Additions/linux/sharedfolders/regops.c

    r77770 r77853  
    838838 */
    839839void vbsf_reg_write_sync_page_cache(struct address_space *mapping, loff_t offFile, uint32_t cbRange,
    840                                     uint8_t const *pbSrcBuf, struct page **papSrcPages, uint32_t offSrcPage)
    841 {
     840                                    uint8_t const *pbSrcBuf, struct page **papSrcPages, uint32_t offSrcPage, size_t cSrcPages)
     841{
     842    Assert(offSrcPage < PAGE_SIZE);
    842843    if (mapping && mapping->nrpages > 0) {
    843844        /*
     
    868869                        uint32_t const cbSrc0 = PAGE_SIZE - offSrcPage;
    869870                        uint8_t const *pbSrc  = (uint8_t const *)kmap(papSrcPages[0]);
     871                        AssertMsg(cSrcPages >= 1, ("offFile=%#llx cbRange=%#zx cbToCopy=%#zx\n", offFile, cbRange, cbToCopy));
    870872                        memcpy(&pbDst[offDstPage], &pbSrc[offSrcPage], RT_MIN(cbToCopy, cbSrc0));
    871873                        kunmap(papSrcPages[0]);
    872874                        if (cbToCopy > cbSrc0) {
     875                            AssertMsg(cSrcPages >= 2, ("offFile=%#llx cbRange=%#zx cbToCopy=%#zx\n", offFile, cbRange, cbToCopy));
    873876                            pbSrc = (uint8_t const *)kmap(papSrcPages[1]);
    874877                            memcpy(&pbDst[offDstPage + cbSrc0], pbSrc, cbToCopy - cbSrc0);
     
    893896             * Advance.
    894897             */
    895             cbRange -= cbToCopy;
    896             offFile += cbToCopy;
    897898            if (pbSrcBuf)
    898899                pbSrcBuf += cbToCopy;
     
    900901            {
    901902                offSrcPage += cbToCopy;
     903                Assert(offSrcPage < PAGE_SIZE * 2);
    902904                if (offSrcPage >= PAGE_SIZE) {
    903905                    offSrcPage &= PAGE_OFFSET_MASK;
    904906                    papSrcPages++;
     907# ifdef VBOX_STRICT
     908                    Assert(cSrcPages > 0);
     909                    cSrcPages--;
     910# endif
    905911                }
    906912            }
     913            offFile += cbToCopy;
     914            cbRange -= cbToCopy;
    907915        }
    908916    }
     917    RT_NOREF(cSrcPages);
    909918}
    910919
     
    979988
    980989                vbsf_reg_write_sync_page_cache(inode->i_mapping, offFile, cbActual, NULL /*pbKrnlBuf*/,
    981                                                papPages, (uintptr_t)buf & PAGE_OFFSET_MASK);
     990                                               papPages, (uintptr_t)buf & PAGE_OFFSET_MASK, cPages);
    982991                vbsf_unlock_user_pages(papPages, cPages, false /*fSetDirty*/, fLockPgHack);
    983992
     
    10991108                    AssertStmt(cbRet <= (ssize_t)size, cbRet = size);
    11001109                    vbsf_reg_write_sync_page_cache(mapping, pos, (uint32_t)cbRet, pReq->abData,
    1101                                                    NULL /*papSrcPages*/, 0 /*offSrcPage0*/);
     1110                                                   NULL /*papSrcPages*/, 0 /*offSrcPage0*/, 0 /*cSrcPages*/);
    11021111                    pos += cbRet;
    11031112                    *off = pos;
     
    11341143                        AssertStmt(cbRet <= (ssize_t)size, cbRet = size);
    11351144                        vbsf_reg_write_sync_page_cache(mapping, pos, (uint32_t)cbRet, (uint8_t const *)pvBounce,
    1136                                                        NULL /*papSrcPages*/, 0 /*offSrcPage0*/);
     1145                                                       NULL /*papSrcPages*/, 0 /*offSrcPage0*/, 0 /*cSrcPages*/);
    11371146                        pos += cbRet;
    11381147                        *off = pos;
     
    18601869                AssertStmt(cbActual <= cbChunk, cbActual = cbChunk);
    18611870
    1862                 vbsf_reg_write_sync_page_cache(mapping, offFile, (uint32_t)cbRet, NULL /*pbSrcBuf*/, papPages, offPage0);
     1871                vbsf_reg_write_sync_page_cache(mapping, offFile, cbActual, NULL /*pbSrcBuf*/, papPages, offPage0, cPages);
    18631872                vbsf_iter_unlock_pages(iter, papPages, cPages, false /*fSetDirty*/);
    18641873
     
    20022011                        AssertStmt(cbRet <= (ssize_t)cbToWrite, cbRet = cbToWrite);
    20032012                        vbsf_reg_write_sync_page_cache(mapping, offFile, (uint32_t)cbRet, pReq->abData,
    2004                                                        NULL /*papSrcPages*/, 0 /*offSrcPage0*/);
     2013                                                       NULL /*papSrcPages*/, 0 /*offSrcPage0*/, 0 /*cSrcPages*/);
    20052014                        kio->ki_pos = offFile += cbRet;
    20062015                        if (offFile > i_size_read(inode))
     
    23502359
    23512360
     2361#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
     2362/**
     2363 * Copy a datablock from one file to another on the host side.
     2364 */
     2365static ssize_t vbsf_reg_copy_file_range(struct file *pFileSrc, loff_t offSrc, struct file *pFileDst, loff_t offDst,
     2366                                        size_t cbRange, unsigned int fFlags)
     2367{
     2368    ssize_t cbRet;
     2369    if (g_uSfLastFunction >= SHFL_FN_COPY_FILE_PART) {
     2370        struct inode           *pInodeSrc     = pFileSrc->f_inode;
     2371        struct vbsf_inode_info *pInodeInfoSrc = VBSF_GET_INODE_INFO(pInodeSrc);
     2372        struct vbsf_super_info *pSuperInfoSrc = VBSF_GET_SUPER_INFO(pInodeSrc->i_sb);
     2373        struct vbsf_reg_info   *pFileInfoSrc  = (struct vbsf_reg_info *)pFileSrc->private_data;
     2374        struct inode           *pInodeDst     = pInodeSrc;
     2375        struct vbsf_inode_info *pInodeInfoDst = VBSF_GET_INODE_INFO(pInodeDst);
     2376        struct vbsf_super_info *pSuperInfoDst = VBSF_GET_SUPER_INFO(pInodeDst->i_sb);
     2377        struct vbsf_reg_info   *pFileInfoDst  = (struct vbsf_reg_info *)pFileDst->private_data;
     2378        VBOXSFCOPYFILEPARTREQ  *pReq;
     2379
     2380        /*
     2381         * Some extra validation.
     2382         */
     2383        AssertPtrReturn(pInodeInfoSrc, -EOPNOTSUPP);
     2384        Assert(pInodeInfoSrc->u32Magic == SF_INODE_INFO_MAGIC);
     2385        AssertPtrReturn(pInodeInfoDst, -EOPNOTSUPP);
     2386        Assert(pInodeInfoDst->u32Magic == SF_INODE_INFO_MAGIC);
     2387
     2388# if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
     2389        if (!S_ISREG(pInodeSrc->i_mode) || !S_ISREG(pInodeDst->i_mode))
     2390            return S_ISDIR(pInodeSrc->i_mode) || S_ISDIR(pInodeDst->i_mode) ? -EISDIR : -EINVAL;
     2391# endif
     2392
     2393        /*
     2394         * Allocate the request and issue it.
     2395         */
     2396        pReq = (VBOXSFCOPYFILEPARTREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
     2397        if (pReq) {
     2398            int vrc = VbglR0SfHostReqCopyFilePart(pSuperInfoSrc->map.root, pFileInfoSrc->Handle.hHost, offSrc,
     2399                                                  pSuperInfoDst->map.root, pFileInfoDst->Handle.hHost, offDst,
     2400                                                  cbRange, 0 /*fFlags*/, pReq);
     2401            if (RT_SUCCESS(vrc))
     2402                cbRet = pReq->Parms.cb64ToCopy.u.value64;
     2403            else if (vrc == VERR_NOT_IMPLEMENTED)
     2404                cbRet = -EOPNOTSUPP;
     2405            else
     2406                cbRet = -RTErrConvertToErrno(vrc);
     2407
     2408            VbglR0PhysHeapFree(pReq);
     2409        } else
     2410            cbRet = -ENOMEM;
     2411    } else {
     2412        cbRet = -EOPNOTSUPP;
     2413    }
     2414    SFLOGFLOW(("vbsf_reg_copy_file_range: returns %zd\n", cbRet));
     2415    return cbRet;
     2416}
     2417#endif /* > 4.5 */
     2418
    23522419#ifdef SFLOG_ENABLED
    23532420/*
     
    25232590 */
    25242591struct file_operations vbsf_reg_fops = {
    2525     .open        = vbsf_reg_open,
    2526     .read        = vbsf_reg_read,
    2527     .write       = vbsf_reg_write,
     2592    .open            = vbsf_reg_open,
     2593    .read            = vbsf_reg_read,
     2594    .write           = vbsf_reg_write,
    25282595#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
    2529     .read_iter   = vbsf_reg_read_iter,
    2530     .write_iter  = vbsf_reg_write_iter,
     2596    .read_iter       = vbsf_reg_read_iter,
     2597    .write_iter      = vbsf_reg_write_iter,
    25312598#endif
    2532     .release     = vbsf_reg_release,
     2599    .release         = vbsf_reg_release,
    25332600#ifdef SFLOG_ENABLED
    2534     .mmap        = vbsf_reg_mmap,
     2601    .mmap            = vbsf_reg_mmap,
    25352602#else
    2536     .mmap        = generic_file_mmap,
     2603    .mmap            = generic_file_mmap,
    25372604#endif
    25382605#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
     
    25412608 * cached.  Investigate. */
    25422609# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
    2543     .splice_read = vbsf_splice_read,
     2610    .splice_read     = vbsf_splice_read,
    25442611# else
    2545     .sendfile    = generic_file_sendfile,
     2612    .sendfile        = generic_file_sendfile,
    25462613# endif
    2547     .aio_read    = generic_file_aio_read,
    2548     .aio_write   = generic_file_aio_write,
     2614    .aio_read        = generic_file_aio_read,
     2615    .aio_write       = generic_file_aio_write,
    25492616# endif
    25502617#endif
    2551     .llseek      = vbsf_reg_llseek,
    2552     .fsync       = vbsf_reg_fsync,
     2618    .llseek          = vbsf_reg_llseek,
     2619    .fsync           = vbsf_reg_fsync,
     2620#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
     2621    .copy_file_range = vbsf_reg_copy_file_range,
     2622#endif
    25532623};
    25542624
  • trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.c

    r77741 r77853  
    6262VBGLSFCLIENT g_SfClient;
    6363uint32_t     g_fHostFeatures = 0;
     64/** Last valid shared folders function number. */
     65uint32_t     g_uSfLastFunction = SHFL_FN_SET_FILE_SIZE;
     66/** Shared folders features. */
     67uint64_t     g_fSfFeatures = 0;
    6468
    6569/** Protects all the vbsf_inode_info::HandleList lists. */
     
    853857        g_fHostFeatures = 0;
    854858    }
    855     LogRelFunc(("g_fHostFeatures=%#x\n", g_fHostFeatures));
     859
     860    VbglR0SfHostReqQueryFeaturesSimple(&g_fSfFeatures, &g_uSfLastFunction);
     861    LogRelFunc(("g_fHostFeatures=%#x g_fSfFeatures=%#RX64 g_uSfLastFunction=%u\n",
     862                g_fHostFeatures, g_fSfFeatures, g_uSfLastFunction));
    856863
    857864    vrc = VbglR0SfSetUtf8(&g_SfClient);
  • trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.h

    r77743 r77853  
    110110extern VBGLSFCLIENT                    g_SfClient;
    111111extern spinlock_t                      g_SfHandleLock;
     112extern uint32_t                        g_uSfLastFunction;
     113extern uint64_t                        g_fSfFeatures;
    112114
    113115extern struct inode_operations         vbsf_dir_iops;
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