Changeset 77770 in vbox for trunk/src/VBox
- Timestamp:
- Mar 18, 2019 7:36:48 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/linux/sharedfolders/regops.c
r77741 r77770 49 49 # include <linux/splice.h> 50 50 #endif 51 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 10) 52 # include <linux/swap.h> /* for mark_page_accessed */ 53 #endif 51 54 #include <iprt/err.h> 52 55 … … 61 64 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0) 62 65 # define vm_fault_t int 66 #endif 67 68 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 20) 69 # define pgoff_t unsigned long 63 70 #endif 64 71 … … 827 834 828 835 /** 829 * Wrapper around invalidate_mapping_pages() for page cache invalidation so that 830 * the changes written via vbsf_reg_write are made visible to mmap users. 831 */ 832 DECLINLINE(void) vbsf_reg_write_invalidate_mapping_range(struct address_space *mapping, loff_t offStart, loff_t offEnd) 833 { 834 /* 835 * Only bother with this if the mapping has any pages in it. 836 * 837 * Note! According to the docs, the last parameter, end, is inclusive (we 838 * would have named it 'last' to indicate this). 839 * 840 * Note! The pre-2.6.12 function might not do enough to sure consistency 841 * when any of the pages in the range is already mapped. 842 */ 843 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12) 844 if (mapping) 845 invalidate_inode_pages2_range(mapping, offStart >> PAGE_SHIFT, (offEnd - 1) >> PAGE_SHIFT); 846 # elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21) 847 if (mapping && mapping->nrpages > 0) 848 invalidate_mapping_pages(mapping, offStart >> PAGE_SHIFT, (offEnd - 1) >> PAGE_SHIFT); 849 # elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 60) && 0 /** @todo invalidate_mapping_pages was added in 2.5.60, but exported in 2.6.21 */ 850 if (mapping && mapping->nrpages > 0) 851 invalidate_mapping_pages(mapping, offStart >> PAGE_SHIFT, (offEnd - 1) >> PAGE_SHIFT); 852 # else 853 /** @todo ... */ 854 RT_NOREF(mapping, offStart, offEnd); 836 * Helper the synchronizes the page cache content with something we just wrote 837 * to the host. 838 */ 839 void 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 { 842 if (mapping && mapping->nrpages > 0) { 843 /* 844 * Work the pages in the write range. 845 */ 846 while (cbRange > 0) { 847 /* 848 * Lookup the page at offFile. We're fine if there aren't 849 * any there. We're skip if it's dirty or is being written 850 * back, at least for now. 851 */ 852 size_t const offDstPage = offFile & PAGE_OFFSET_MASK; 853 size_t const cbToCopy = RT_MIN(PAGE_SIZE - offDstPage, cbRange); 854 pgoff_t const idxPage = offFile >> PAGE_SHIFT; 855 struct page *pDstPage = find_lock_page(mapping, idxPage); 856 if (pDstPage) { 857 if ( pDstPage->mapping == mapping /* ignore if re-purposed (paranoia) */ 858 && pDstPage->index == idxPage 859 && !PageDirty(pDstPage) /* ignore if dirty */ 860 && !PageWriteback(pDstPage) /* ignore if being written back */ ) { 861 /* 862 * Map the page and do the copying. 863 */ 864 uint8_t *pbDst = (uint8_t *)kmap(pDstPage); 865 if (pbSrcBuf) 866 memcpy(&pbDst[offDstPage], pbSrcBuf, cbToCopy); 867 else { 868 uint32_t const cbSrc0 = PAGE_SIZE - offSrcPage; 869 uint8_t const *pbSrc = (uint8_t const *)kmap(papSrcPages[0]); 870 memcpy(&pbDst[offDstPage], &pbSrc[offSrcPage], RT_MIN(cbToCopy, cbSrc0)); 871 kunmap(papSrcPages[0]); 872 if (cbToCopy > cbSrc0) { 873 pbSrc = (uint8_t const *)kmap(papSrcPages[1]); 874 memcpy(&pbDst[offDstPage + cbSrc0], pbSrc, cbToCopy - cbSrc0); 875 kunmap(papSrcPages[1]); 876 } 877 } 878 kunmap(pDstPage); 879 flush_dcache_page(pDstPage); 880 if (cbToCopy == PAGE_SIZE) 881 SetPageUptodate(pDstPage); 882 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 10) 883 mark_page_accessed(pDstPage); 855 884 # endif 885 } else 886 SFLOGFLOW(("vbsf_reg_write_sync_page_cache: Skipping page %p: mapping=%p (vs %p) writeback=%d offset=%#lx (vs%#lx)\n", 887 pDstPage, pDstPage->mapping, mapping, PageWriteback(pDstPage), pDstPage->index, idxPage)); 888 unlock_page(pDstPage); 889 vbsf_put_page(pDstPage); 890 } 891 892 /* 893 * Advance. 894 */ 895 cbRange -= cbToCopy; 896 offFile += cbToCopy; 897 if (pbSrcBuf) 898 pbSrcBuf += cbToCopy; 899 else 900 { 901 offSrcPage += cbToCopy; 902 if (offSrcPage >= PAGE_SIZE) { 903 offSrcPage &= PAGE_OFFSET_MASK; 904 papSrcPages++; 905 } 906 } 907 } 908 } 856 909 } 857 910 … … 918 971 */ 919 972 rc = VbglR0SfHostReqWritePgLst(sf_g->map.root, pReq, sf_r->Handle.hHost, offFile, cbChunk, cPages); 920 921 vbsf_unlock_user_pages(papPages, cPages, false /*fSetDirty*/, fLockPgHack);922 923 973 if (RT_SUCCESS(rc)) { 924 974 /* … … 927 977 uint32_t cbActual = pReq->Parms.cb32Write.u.value32; 928 978 AssertStmt(cbActual <= cbChunk, cbActual = cbChunk); 979 980 vbsf_reg_write_sync_page_cache(inode->i_mapping, offFile, cbActual, NULL /*pbKrnlBuf*/, 981 papPages, (uintptr_t)buf & PAGE_OFFSET_MASK); 982 vbsf_unlock_user_pages(papPages, cPages, false /*fSetDirty*/, fLockPgHack); 983 929 984 cbRet += cbActual; 930 985 offFile += cbActual; … … 933 988 if (offFile > i_size_read(inode)) 934 989 i_size_write(inode, offFile); 935 vbsf_reg_write_invalidate_mapping_range(inode->i_mapping, offFile - cbActual, offFile);936 990 sf_i->force_restat = 1; /* mtime (and size) may have changed */ 937 991 … … 943 997 break; 944 998 } 945 } else if (rc == VERR_NO_MEMORY && cMaxPages > 4) {946 /*947 * The host probably doesn't have enough heap to handle the948 * request, reduce the page count and retry.949 */950 cMaxPages /= 4;951 Assert(cMaxPages > 0);952 999 } else { 953 /* 954 * If we've successfully written stuff, return it rather than 955 * the error. (Not sure if this is such a great idea...) 956 */ 957 if (cbRet > 0) 958 *off = offFile; 959 else 960 cbRet = -EPROTO; 961 break; 1000 vbsf_unlock_user_pages(papPages, cPages, false /*fSetDirty*/, fLockPgHack); 1001 if (rc == VERR_NO_MEMORY && cMaxPages > 4) { 1002 /* 1003 * The host probably doesn't have enough heap to handle the 1004 * request, reduce the page count and retry. 1005 */ 1006 cMaxPages /= 4; 1007 Assert(cMaxPages > 0); 1008 } else { 1009 /* 1010 * If we've successfully written stuff, return it rather than 1011 * the error. (Not sure if this is such a great idea...) 1012 */ 1013 if (cbRet > 0) 1014 *off = offFile; 1015 else 1016 cbRet = -EPROTO; 1017 break; 1018 } 962 1019 } 963 1020 } … … 1041 1098 cbRet = pReq->Parms.cb32Write.u.value32; 1042 1099 AssertStmt(cbRet <= (ssize_t)size, cbRet = size); 1100 vbsf_reg_write_sync_page_cache(mapping, pos, (uint32_t)cbRet, pReq->abData, 1101 NULL /*papSrcPages*/, 0 /*offSrcPage0*/); 1043 1102 pos += cbRet; 1044 1103 *off = pos; 1045 1104 if (pos > i_size_read(inode)) 1046 1105 i_size_write(inode, pos); 1047 vbsf_reg_write_invalidate_mapping_range(mapping, pos - cbRet, pos);1048 1106 } else 1049 1107 cbRet = -EPROTO; … … 1075 1133 cbRet = pReq->Parms.cb32Write.u.value32; 1076 1134 AssertStmt(cbRet <= (ssize_t)size, cbRet = size); 1135 vbsf_reg_write_sync_page_cache(mapping, pos, (uint32_t)cbRet, (uint8_t const *)pvBounce, 1136 NULL /*papSrcPages*/, 0 /*offSrcPage0*/); 1077 1137 pos += cbRet; 1078 1138 *off = pos; 1079 1139 if (pos > i_size_read(inode)) 1080 1140 i_size_write(inode, pos); 1081 vbsf_reg_write_invalidate_mapping_range(mapping, pos - cbRet, pos);1082 1141 } else 1083 1142 cbRet = -EPROTO; … … 1794 1853 SFLOGFLOW(("vbsf_reg_write_iter_locking: VbglR0SfHostReqWritePgLst -> %d (cbActual=%#x cbChunk=%#zx of %#zx cPages=%#zx offPage0=%#x\n", 1795 1854 rc, pReq->Parms.cb32Write.u.value32, cbChunk, cbToWrite, cPages, offPage0)); 1796 1797 vbsf_iter_unlock_pages(iter, papPages, cPages, false /*fSetDirty*/);1798 1799 1855 if (RT_SUCCESS(rc)) { 1800 1856 /* … … 1803 1859 uint32_t cbActual = pReq->Parms.cb32Write.u.value32; 1804 1860 AssertStmt(cbActual <= cbChunk, cbActual = cbChunk); 1861 1862 vbsf_reg_write_sync_page_cache(mapping, offFile, (uint32_t)cbRet, NULL /*pbSrcBuf*/, papPages, offPage0); 1863 vbsf_iter_unlock_pages(iter, papPages, cPages, false /*fSetDirty*/); 1864 1805 1865 cbRet += cbActual; 1806 1866 offFile += cbActual; … … 1809 1869 if (offFile > i_size_read(inode)) 1810 1870 i_size_write(inode, offFile); 1811 vbsf_reg_write_invalidate_mapping_range(mapping, offFile - cbActual, offFile);1812 1871 sf_i->force_restat = 1; /* mtime (and size) may have changed */ 1813 1872 … … 1826 1885 * Try rewind the iter structure. 1827 1886 */ 1828 bool const fRewindOkay = vbsf_iter_rewind(iter, &Stash, cbChunk, cbChunk); 1887 bool fRewindOkay; 1888 vbsf_iter_unlock_pages(iter, papPages, cPages, false /*fSetDirty*/); 1889 fRewindOkay = vbsf_iter_rewind(iter, &Stash, cbChunk, cbChunk); 1829 1890 if (rc == VERR_NO_MEMORY && cMaxPages > 4 && fRewindOkay) { 1830 1891 /* … … 1940 2001 cbRet = pReq->Parms.cb32Write.u.value32; 1941 2002 AssertStmt(cbRet <= (ssize_t)cbToWrite, cbRet = cbToWrite); 2003 vbsf_reg_write_sync_page_cache(mapping, offFile, (uint32_t)cbRet, pReq->abData, 2004 NULL /*papSrcPages*/, 0 /*offSrcPage0*/); 1942 2005 kio->ki_pos = offFile += cbRet; 1943 2006 if (offFile > i_size_read(inode)) 1944 2007 i_size_write(inode, offFile); 1945 vbsf_reg_write_invalidate_mapping_range(mapping, offFile - cbRet, offFile);1946 2008 # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) 1947 2009 if ((size_t)cbRet < cbToWrite)
Note:
See TracChangeset
for help on using the changeset viewer.