Changeset 77631 in vbox for trunk/src/VBox/Additions/linux/sharedfolders
- Timestamp:
- Mar 10, 2019 4:14:09 AM (6 years ago)
- Location:
- trunk/src/VBox/Additions/linux/sharedfolders
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/linux/sharedfolders/regops.c
r77628 r77631 923 923 i_size_write(inode, offFile); 924 924 vbsf_reg_write_invalidate_mapping_range(inode->i_mapping, offFile - cbActual, offFile); 925 sf_i->force_restat = 1; /* mtime (and size) may have changed */ 925 926 926 927 /* … … 949 950 break; 950 951 } 951 sf_i->force_restat = 1; /* mtime (and size) may have changed */952 952 } 953 953 } … … 1026 1026 if (copy_from_user(pReq->abData, buf, size) == 0) { 1027 1027 int vrc = VbglR0SfHostReqWriteEmbedded(sf_g->map.root, pReq, sf_r->Handle.hHost, 1028 pos, (uint32_t)size);1028 pos, (uint32_t)size); 1029 1029 if (RT_SUCCESS(vrc)) { 1030 1030 cbRet = pReq->Parms.cb32Write.u.value32; … … 1642 1642 1643 1643 1644 /** 1645 * Worker for vbsf_reg_write_iter() that deals with larger writes using page 1646 * locking. 1647 */ 1648 static ssize_t vbsf_reg_write_iter_locking(struct kiocb *kio, struct iov_iter *iter, size_t cbToWrite, loff_t offFile, 1649 struct vbsf_super_info *sf_g, struct vbsf_reg_info *sf_r, 1650 struct inode *inode, struct vbsf_inode_info *sf_i, struct address_space *mapping) 1651 { 1652 /* 1653 * Estimate how many pages we may possible submit in a single request so 1654 * that we can allocate matching request buffer and page array. 1655 */ 1656 struct page *apPagesStack[16]; 1657 struct page **papPages = &apPagesStack[0]; 1658 struct page **papPagesFree = NULL; 1659 VBOXSFWRITEPGLSTREQ *pReq; 1660 ssize_t cbRet = 0; 1661 size_t cMaxPages = vbsf_iter_max_span_of_pages(iter); 1662 cMaxPages = RT_MIN(RT_MAX(sf_g->cMaxIoPages, 2), cMaxPages); 1663 1664 pReq = (VBOXSFWRITEPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFWRITEPGLSTREQ, PgLst.aPages[cMaxPages])); 1665 while (!pReq && cMaxPages > 4) { 1666 cMaxPages /= 2; 1667 pReq = (VBOXSFWRITEPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFWRITEPGLSTREQ, PgLst.aPages[cMaxPages])); 1668 } 1669 if (pReq && cMaxPages > RT_ELEMENTS(apPagesStack)) 1670 papPagesFree = papPages = kmalloc(cMaxPages * sizeof(sizeof(papPages[0])), GFP_KERNEL); 1671 if (pReq && papPages) { 1672 1673 /* 1674 * The write loop. 1675 */ 1676 struct vbsf_iter_stash Stash = VBSF_ITER_STASH_INITIALIZER; 1677 do { 1678 /* 1679 * Grab as many pages as we can. This means that if adjacent 1680 * segments both starts and ends at a page boundrary, we can 1681 * do them both in the same transfer from the host. 1682 */ 1683 size_t cPages = 0; 1684 size_t cbChunk = 0; 1685 size_t offPage0 = 0; 1686 int rc = vbsf_iter_lock_pages(iter, false /*fWrite*/, &Stash, cMaxPages, papPages, &cPages, &offPage0, &cbChunk); 1687 if (rc == 0) { 1688 size_t iPage = cPages; 1689 while (iPage-- > 0) 1690 pReq->PgLst.aPages[iPage] = page_to_phys(papPages[iPage]); 1691 pReq->PgLst.offFirstPage = (uint16_t)offPage0; 1692 AssertStmt(cbChunk <= cbToWrite, cbChunk = cbToWrite); 1693 } else { 1694 cbRet = rc; 1695 break; 1696 } 1697 1698 /* 1699 * Issue the request and unlock the pages. 1700 */ 1701 rc = VbglR0SfHostReqWritePgLst(sf_g->map.root, pReq, sf_r->Handle.hHost, offFile, cbChunk, cPages); 1702 SFLOGFLOW(("vbsf_reg_write_iter_locking: VbglR0SfHostReqWritePgLst -> %d (cbActual=%#x cbChunk=%#zx of %#zx cPages=%#zx offPage0=%#x\n", 1703 rc, pReq->Parms.cb32Write.u.value32, cbChunk, cbToWrite, cPages, offPage0)); 1704 1705 vbsf_iter_unlock_pages(iter, papPages, cPages, false /*fSetDirty*/); 1706 1707 if (RT_SUCCESS(rc)) { 1708 /* 1709 * Success, advance position and buffer. 1710 */ 1711 uint32_t cbActual = pReq->Parms.cb32Write.u.value32; 1712 AssertStmt(cbActual <= cbChunk, cbActual = cbChunk); 1713 cbRet += cbActual; 1714 offFile += cbActual; 1715 kio->ki_pos = offFile; 1716 cbToWrite -= cbActual; 1717 if (offFile > i_size_read(inode)) 1718 i_size_write(inode, offFile); 1719 vbsf_reg_write_invalidate_mapping_range(mapping, offFile - cbActual, offFile); 1720 sf_i->force_restat = 1; /* mtime (and size) may have changed */ 1721 1722 /* 1723 * Are we done already? 1724 */ 1725 if (!cbToWrite) 1726 break; 1727 if (cbActual < cbChunk) { /* We ASSUME end-of-file here. */ 1728 if (vbsf_iter_rewind(iter, &Stash, cbChunk - cbActual, cbActual)) 1729 iov_iter_truncate(iter, 0); 1730 break; 1731 } 1732 } else { 1733 /* 1734 * Try rewind the iter structure. 1735 */ 1736 bool const fRewindOkay = vbsf_iter_rewind(iter, &Stash, cbChunk, cbChunk); 1737 if (rc == VERR_NO_MEMORY && cMaxPages > 4 && fRewindOkay) { 1738 /* 1739 * The host probably doesn't have enough heap to handle the 1740 * request, reduce the page count and retry. 1741 */ 1742 cMaxPages /= 4; 1743 Assert(cMaxPages > 0); 1744 } else { 1745 /* 1746 * If we've successfully written stuff, return it rather than 1747 * the error. (Not sure if this is such a great idea...) 1748 */ 1749 if (cbRet <= 0) 1750 cbRet = -EPROTO; 1751 break; 1752 } 1753 } 1754 } while (cbToWrite > 0); 1755 1756 vbsf_iter_cleanup_stash(iter, &Stash); 1757 } 1758 else 1759 cbRet = -ENOMEM; 1760 if (papPagesFree) 1761 kfree(papPages); 1762 if (pReq) 1763 VbglR0PhysHeapFree(pReq); 1764 SFLOGFLOW(("vbsf_reg_write_iter_locking: returns %#zx (%zd)\n", cbRet, cbRet)); 1765 return cbRet; 1766 } 1767 1768 1769 1770 /** 1771 * Write from I/O vector iterator. 1772 * 1773 * @returns Number of bytes written on success, negative errno on error. 1774 * @param kio The kernel I/O control block (or something like that). 1775 * @param iter The I/O vector iterator describing the buffer. 1776 */ 1644 1777 static ssize_t vbsf_reg_write_iter(struct kiocb *kio, struct iov_iter *iter) 1645 1778 { 1646 SFLOGFLOW(("vbsf_reg_write_iter: -> EINVAL\n")); 1647 return -EINVAL; 1779 size_t cbToWrite = iov_iter_count(iter); 1780 struct inode *inode = VBSF_GET_F_DENTRY(kio->ki_filp)->d_inode; 1781 struct vbsf_inode_info *sf_i = VBSF_GET_INODE_INFO(inode); 1782 struct address_space *mapping = inode->i_mapping; 1783 1784 struct vbsf_reg_info *sf_r = kio->ki_filp->private_data; 1785 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb); 1786 loff_t offFile = kio->ki_pos; 1787 1788 SFLOGFLOW(("vbsf_reg_write_iter: inode=%p file=%p size=%#zx off=%#llx type=%#x\n", 1789 inode, kio->ki_filp, cbToWrite, offFile, iter->type)); 1790 AssertReturn(S_ISREG(inode->i_mode), -EINVAL); 1791 1792 /* 1793 * Enforce APPEND flag. 1794 */ 1795 /** @todo This should be handled by the host, it returning the new file 1796 * offset when appending. We may have an outdated i_size value here! */ 1797 if (kio->ki_flags & IOCB_APPEND) 1798 kio->ki_pos = offFile = i_size_read(inode); 1799 1800 /* 1801 * Do we have anything at all to do here? 1802 */ 1803 if (!cbToWrite) 1804 return 0; 1805 1806 /* 1807 * Now now we reject async I/O requests. 1808 */ 1809 if (!is_sync_kiocb(kio)) { 1810 SFLOGFLOW(("vbsf_reg_write_iter: async I/O not yet supported\n")); /** @todo extend FsPerf with AIO tests. */ 1811 return -EOPNOTSUPP; 1812 } 1813 1814 /* 1815 * If there are active writable mappings, coordinate with any 1816 * pending writes via those. 1817 */ 1818 if ( mapping 1819 && mapping->nrpages > 0 1820 && mapping_writably_mapped(mapping)) { 1821 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) 1822 int err = filemap_fdatawait_range(mapping, offFile, offFile + cbToWrite - 1); 1823 if (err) 1824 return err; 1825 #else 1826 /** @todo ... */ 1827 #endif 1828 } 1829 1830 /* 1831 * For small requests, try use an embedded buffer provided we get a heap block 1832 * that does not cross page boundraries (see host code). 1833 */ 1834 if (cbToWrite <= PAGE_SIZE / 4 * 3 - RT_UOFFSETOF(VBOXSFWRITEEMBEDDEDREQ, abData[0]) /* see allocator */) { 1835 uint32_t const cbReq = RT_UOFFSETOF(VBOXSFWRITEEMBEDDEDREQ, abData[0]) + cbToWrite; 1836 VBOXSFWRITEEMBEDDEDREQ *pReq = (VBOXSFWRITEEMBEDDEDREQ *)VbglR0PhysHeapAlloc(cbReq); 1837 if (pReq) { 1838 if ((PAGE_SIZE - ((uintptr_t)pReq & PAGE_OFFSET_MASK)) >= cbReq) { 1839 ssize_t cbRet; 1840 if (copy_from_iter(pReq->abData, cbToWrite, iter) == cbToWrite) { 1841 int vrc = VbglR0SfHostReqWriteEmbedded(sf_g->map.root, pReq, sf_r->Handle.hHost, 1842 offFile, (uint32_t)cbToWrite); 1843 if (RT_SUCCESS(vrc)) { 1844 cbRet = pReq->Parms.cb32Write.u.value32; 1845 AssertStmt(cbRet <= (ssize_t)cbToWrite, cbRet = cbToWrite); 1846 kio->ki_pos = offFile += cbRet; 1847 if (offFile > i_size_read(inode)) 1848 i_size_write(inode, offFile); 1849 vbsf_reg_write_invalidate_mapping_range(mapping, offFile - cbRet, offFile); 1850 # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) 1851 if ((size_t)cbRet < cbToWrite) 1852 iov_iter_revert(iter, cbToWrite - cbRet); 1853 # endif 1854 } else 1855 cbRet = -EPROTO; 1856 sf_i->force_restat = 1; /* mtime (and size) may have changed */ 1857 } else 1858 cbRet = -EFAULT; 1859 VbglR0PhysHeapFree(pReq); 1860 SFLOGFLOW(("vbsf_reg_write_iter: returns %#zx (%zd)\n", cbRet, cbRet)); 1861 return cbRet; 1862 } 1863 VbglR0PhysHeapFree(pReq); 1864 } 1865 } 1866 1867 /* 1868 * Otherwise do the page locking thing. 1869 */ 1870 return vbsf_reg_write_iter_locking(kio, iter, cbToWrite, offFile, sf_g, sf_r, inode, sf_i, mapping); 1648 1871 } 1649 1872 -
trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.h
r77628 r77631 54 54 #include <iprt/asm.h> 55 55 #include "vbsfmount.h" 56 57 58 /* 59 * Logging wrappers. 60 */ 61 #if 1 62 # define TRACE() LogFunc(("tracepoint\n")) 63 # define SFLOGFLOW(aArgs) Log(aArgs) 64 # define SFLOG2(aArgs) Log2(aArgs) 65 # define SFLOG3(aArgs) Log3(aArgs) 66 # ifdef LOG_ENABLED 67 # define SFLOG_ENABLED 1 68 # endif 69 #else 70 # define TRACE() RTLogBackdoorPrintf("%s: tracepoint\n", __FUNCTION__) 71 # define SFLOGFLOW(aArgs) RTLogBackdoorPrintf aArgs 72 # define SFLOG2(aArgs) RTLogBackdoorPrintf aArgs 73 # define SFLOG3(aArgs) RTLogBackdoorPrintf aArgs 74 # define SFLOG_ENABLED 1 75 #endif 56 76 57 77 … … 313 333 DECLINLINE(void) vbsf_dentry_set_update_jiffies(struct dentry *pDirEntry, unsigned long uToSet) 314 334 { 335 /*SFLOG3(("vbsf_dentry_set_update_jiffies: %p: %lx -> %#lx\n", pDirEntry, (unsigned long)pDirEntry->d_fsdata, uToSet));*/ 315 336 pDirEntry->d_fsdata = (void *)uToSet; 316 337 } … … 393 414 } 394 415 395 #if 1396 # define TRACE() LogFunc(("tracepoint\n"))397 # define SFLOGFLOW(aArgs) Log(aArgs)398 # define SFLOG2(aArgs) Log2(aArgs)399 # define SFLOG3(aArgs) Log3(aArgs)400 # ifdef LOG_ENABLED401 # define SFLOG_ENABLED 1402 # endif403 #else404 # define TRACE() RTLogBackdoorPrintf("%s: tracepoint\n", __FUNCTION__)405 # define SFLOGFLOW(aArgs) RTLogBackdoorPrintf aArgs406 # define SFLOG2(aArgs) RTLogBackdoorPrintf aArgs407 # define SFLOG3(aArgs) RTLogBackdoorPrintf aArgs408 # define SFLOG_ENABLED 1409 #endif410 411 416 #endif /* !GA_INCLUDED_SRC_linux_sharedfolders_vfsmod_h */
Note:
See TracChangeset
for help on using the changeset viewer.