VirtualBox

Changeset 77853 in vbox for trunk/src/VBox/Additions/linux


Ignore:
Timestamp:
Mar 22, 2019 8:54:14 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
129537
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/src/VBox/Additions/linux/sharedfolders
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • 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.

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