Changeset 77626 in vbox for trunk/src/VBox
- Timestamp:
- Mar 8, 2019 9:44:49 PM (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
r77561 r77626 29 29 */ 30 30 31 32 /********************************************************************************************************************************* 33 * Header Files * 34 *********************************************************************************************************************************/ 31 35 #include "vfsmod.h" 32 36 #include <linux/uio.h> … … 52 56 53 57 58 /********************************************************************************************************************************* 59 * Structures and Typedefs * 60 *********************************************************************************************************************************/ 61 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) 62 /** Used by vbsf_iter_lock_pages() to keep the first page of the next segment. */ 63 struct vbsf_iter_stash { 64 struct page *pPage; 65 size_t off; 66 size_t cb; 67 # if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) 68 size_t offFromEnd; 69 struct iov_iter Copy; 70 # endif 71 }; 72 #endif /* >= 3.16.0 */ 73 /** Initializer for struct vbsf_iter_stash. */ 74 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) 75 # define VBSF_ITER_STASH_INITIALIZER { NULL, 0 } 76 #else 77 # define VBSF_ITER_STASH_INITIALIZER { NULL, 0, ~(size_t)0 } 78 #endif 79 80 81 54 82 /** 55 83 * Called when an inode is released to unlink all handles that might impossibly … … 348 376 #endif /* 2.6.23 <= LINUX_VERSION_CODE < 2.6.31 */ 349 377 378 /** 379 * Helper for deciding wheter we should do a read via the page cache or not. 380 * 381 * By default we will only use the page cache if there is a writable memory 382 * mapping of the file with a chance that it may have modified any of the pages 383 * already. 384 */ 385 DECLINLINE(bool) vbsf_should_use_cached_read(struct file *file, struct address_space *mapping, struct vbsf_super_info *sf_g) 386 { 387 return mapping 388 && mapping->nrpages > 0 389 && mapping_writably_mapped(mapping) 390 && !(file->f_flags & O_DIRECT) 391 && 1 /** @todo make this behaviour configurable at mount time (sf_g) */; 392 } 393 350 394 /** Wrapper around put_page / page_cache_release. */ 351 395 DECLINLINE(void) vbsf_put_page(struct page *pPage) … … 384 428 vbsf_put_page(pPage); 385 429 } 430 } 431 432 433 /** 434 * Worker for vbsf_lock_user_pages_failed_check_kernel() and 435 * vbsf_iter_lock_pages(). 436 */ 437 static int vbsf_lock_kernel_pages(uint8_t *pbStart, bool fWrite, size_t cPages, struct page **papPages) 438 { 439 uintptr_t const uPtrFrom = (uintptr_t)pbStart; 440 uintptr_t const uPtrLast = (uPtrFrom & ~(uintptr_t)PAGE_OFFSET_MASK) + (cPages << PAGE_SHIFT) - 1; 441 uint8_t *pbPage = (uint8_t *)uPtrLast; 442 size_t iPage = cPages; 443 444 /* 445 * Touch the pages first (paranoia^2). 446 */ 447 if (fWrite) { 448 uint8_t volatile *pbProbe = (uint8_t volatile *)uPtrFrom; 449 while (iPage-- > 0) { 450 *pbProbe = *pbProbe; 451 pbProbe += PAGE_SIZE; 452 } 453 } else { 454 uint8_t const *pbProbe = (uint8_t const *)uPtrFrom; 455 while (iPage-- > 0) { 456 ASMProbeReadByte(pbProbe); 457 pbProbe += PAGE_SIZE; 458 } 459 } 460 461 /* 462 * Get the pages. 463 * Note! Fixes here probably applies to rtR0MemObjNativeLockKernel as well. 464 */ 465 iPage = cPages; 466 if ( uPtrFrom >= (unsigned long)__va(0) 467 && uPtrLast < (unsigned long)high_memory) { 468 /* The physical page mapping area: */ 469 while (iPage-- > 0) { 470 struct page *pPage = papPages[iPage] = virt_to_page(pbPage); 471 vbsf_get_page(pPage); 472 pbPage -= PAGE_SIZE; 473 } 474 } else { 475 /* This is vmalloc or some such thing, so go thru page tables: */ 476 while (iPage-- > 0) { 477 struct page *pPage = rtR0MemObjLinuxVirtToPage(pbPage); 478 if (pPage) { 479 papPages[iPage] = pPage; 480 vbsf_get_page(pPage); 481 pbPage -= PAGE_SIZE; 482 } else { 483 while (++iPage < cPages) { 484 pPage = papPages[iPage]; 485 vbsf_put_page(pPage); 486 } 487 return -EFAULT; 488 } 489 } 490 } 491 return 0; 386 492 } 387 493 … … 415 521 #endif 416 522 { 417 uintptr_t const uPtrLast = (uPtrFrom & ~(uintptr_t)PAGE_OFFSET_MASK) + (cPages << PAGE_SHIFT) - 1; 418 uint8_t *pbPage = (uint8_t *)uPtrLast; 419 size_t iPage = cPages; 420 421 /* 422 * Touch the pages first (paranoia^2). 423 */ 424 if (fWrite) { 425 uint8_t volatile *pbProbe = (uint8_t volatile *)uPtrFrom; 426 while (iPage-- > 0) { 427 *pbProbe = *pbProbe; 428 pbProbe += PAGE_SIZE; 429 } 430 } else { 431 uint8_t const *pbProbe = (uint8_t const *)uPtrFrom; 432 while (iPage-- > 0) { 433 ASMProbeReadByte(pbProbe); 434 pbProbe += PAGE_SIZE; 435 } 436 } 437 438 /* 439 * Get the pages. 440 * Note! Fixes here probably applies to rtR0MemObjNativeLockKernel as well. 441 */ 442 iPage = cPages; 443 if ( uPtrFrom >= (unsigned long)__va(0) 444 && uPtrLast < (unsigned long)high_memory) 445 { 446 /* The physical page mapping area: */ 447 while (iPage-- > 0) 448 { 449 struct page *pPage = papPages[iPage] = virt_to_page(pbPage); 450 vbsf_get_page(pPage); 451 pbPage -= PAGE_SIZE; 452 } 453 } 454 else 455 { 456 /* This is vmalloc or some such thing, so go thru page tables: */ 457 while (iPage-- > 0) 458 { 459 struct page *pPage = rtR0MemObjLinuxVirtToPage(pbPage); 460 if (pPage) { 461 papPages[iPage] = pPage; 462 vbsf_get_page(pPage); 463 pbPage -= PAGE_SIZE; 464 } else { 465 while (++iPage < cPages) { 466 pPage = papPages[iPage]; 467 vbsf_put_page(pPage); 468 } 469 return rcFailed; 470 } 471 } 472 } 473 *pfLockPgHack = true; 474 return 0; 523 int rc = vbsf_lock_kernel_pages((uint8_t *)uPtrFrom, fWrite, cPages, papPages); 524 if (rc == 0) { 525 *pfLockPgHack = true; 526 return 0; 527 } 475 528 } 476 529 … … 585 638 pReq = (VBOXSFREADPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFREADPGLSTREQ, PgLst.aPages[cMaxPages])); 586 639 } 587 if (pReq && c Pages > RT_ELEMENTS(apPagesStack))640 if (pReq && cMaxPages > RT_ELEMENTS(apPagesStack)) 588 641 papPagesFree = papPages = kmalloc(cMaxPages * sizeof(sizeof(papPages[0])), GFP_KERNEL); 589 642 if (pReq && papPages) { … … 610 663 pReq->PgLst.aPages[iPage] = page_to_phys(papPages[iPage]); 611 664 } else { 612 /** @todo may need fallback here for kernel addresses during exec. sigh. */613 665 cbRet = rc; 614 666 break; … … 702 754 * mappings around with any kind of pages loaded. 703 755 */ 704 if ( mapping 705 && mapping->nrpages > 0 706 && mapping_writably_mapped(mapping) 707 && !(file->f_flags & O_DIRECT) 708 && 1 /** @todo make this behaviour configurable */ ) 756 if (vbsf_should_use_cached_read(file, mapping, sf_g)) 709 757 return vbsf_reg_read_mapped(file, buf, size, off); 710 758 … … 716 764 uint32_t const cbReq = RT_UOFFSETOF(VBOXSFREADEMBEDDEDREQ, abData[0]) + size; 717 765 VBOXSFREADEMBEDDEDREQ *pReq = (VBOXSFREADEMBEDDEDREQ *)VbglR0PhysHeapAlloc(cbReq); 718 if ( pReq 719 && (PAGE_SIZE - ((uintptr_t)pReq & PAGE_OFFSET_MASK)) >= cbReq) { 720 ssize_t cbRet; 721 int vrc = VbglR0SfHostReqReadEmbedded(sf_g->map.root, pReq, sf_r->Handle.hHost, *off, (uint32_t)size); 722 if (RT_SUCCESS(vrc)) { 723 cbRet = pReq->Parms.cb32Read.u.value32; 724 AssertStmt(cbRet <= (ssize_t)size, cbRet = size); 725 if (copy_to_user(buf, pReq->abData, cbRet) == 0) 726 *off += cbRet; 727 else 728 cbRet = -EFAULT; 729 } else 730 cbRet = -EPROTO; 766 if (pReq) { 767 if ((PAGE_SIZE - ((uintptr_t)pReq & PAGE_OFFSET_MASK)) >= cbReq) { 768 ssize_t cbRet; 769 int vrc = VbglR0SfHostReqReadEmbedded(sf_g->map.root, pReq, sf_r->Handle.hHost, *off, (uint32_t)size); 770 if (RT_SUCCESS(vrc)) { 771 cbRet = pReq->Parms.cb32Read.u.value32; 772 AssertStmt(cbRet <= (ssize_t)size, cbRet = size); 773 if (copy_to_user(buf, pReq->abData, cbRet) == 0) 774 *off += cbRet; 775 else 776 cbRet = -EFAULT; 777 } else 778 cbRet = -EPROTO; 779 VbglR0PhysHeapFree(pReq); 780 return cbRet; 781 } 731 782 VbglR0PhysHeapFree(pReq); 732 return cbRet; 733 } 734 if (pReq) 735 VbglR0PhysHeapFree(pReq); 783 } 736 784 } 737 785 … … 826 874 pReq = (VBOXSFWRITEPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFWRITEPGLSTREQ, PgLst.aPages[cMaxPages])); 827 875 } 828 if (pReq && c Pages > RT_ELEMENTS(apPagesStack))876 if (pReq && cMaxPages > RT_ELEMENTS(apPagesStack)) 829 877 papPagesFree = papPages = kmalloc(cMaxPages * sizeof(sizeof(papPages[0])), GFP_KERNEL); 830 878 if (pReq && papPages) { … … 926 974 struct vbsf_inode_info *sf_i = VBSF_GET_INODE_INFO(inode); 927 975 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb); 928 struct vbsf_reg_info 976 struct vbsf_reg_info *sf_r = file->private_data; 929 977 struct address_space *mapping = inode->i_mapping; 930 978 loff_t pos; … … 934 982 BUG_ON(!sf_g); 935 983 BUG_ON(!sf_r); 936 937 if (!S_ISREG(inode->i_mode)) { 938 LogFunc(("write to non regular file %d\n", inode->i_mode)); 939 return -EINVAL; 940 } 984 AssertReturn(S_ISREG(inode->i_mode), -EINVAL); 941 985 942 986 pos = *off; … … 1044 1088 } 1045 1089 1090 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) 1091 1092 /** 1093 * Companion to vbsf_iter_lock_pages(). 1094 */ 1095 DECLINLINE(void) vbsf_iter_unlock_pages(struct iov_iter *iter, struct page **papPages, size_t cPages, bool fSetDirty) 1096 { 1097 /* We don't mark kernel pages dirty: */ 1098 if (iter->type & ITER_KVEC) 1099 fSetDirty = false; 1100 1101 while (cPages-- > 0) 1102 { 1103 struct page *pPage = papPages[cPages]; 1104 if (fSetDirty && !PageReserved(pPage)) 1105 SetPageDirty(pPage); 1106 vbsf_put_page(pPage); 1107 } 1108 } 1109 1110 1111 /** 1112 * Locks up to @a cMaxPages from the I/O vector iterator, advancing the 1113 * iterator. 1114 * 1115 * @returns 0 on success, negative errno value on failure. 1116 * @param iter The iterator to lock pages from. 1117 * @param fWrite Whether to write (true) or read (false) lock the pages. 1118 * @param pStash Where we stash peek results. 1119 * @param cMaxPages The maximum number of pages to get. 1120 * @param papPages Where to return the locked pages. 1121 * @param pcPages Where to return the number of pages. 1122 * @param poffPage0 Where to return the offset into the first page. 1123 * @param pcbChunk Where to return the number of bytes covered. 1124 */ 1125 static int vbsf_iter_lock_pages(struct iov_iter *iter, bool fWrite, struct vbsf_iter_stash *pStash, size_t cMaxPages, 1126 struct page **papPages, size_t *pcPages, size_t *poffPage0, size_t *pcbChunk) 1127 { 1128 size_t cbChunk = 0; 1129 size_t cPages = 0; 1130 size_t offPage0 = 0; 1131 int rc = 0; 1132 1133 Assert(iov_iter_count(iter) > 0); 1134 if (!(iter->type & ITER_KVEC)) { 1135 /* 1136 * Do we have a stashed page? 1137 */ 1138 if (pStash->pPage) { 1139 papPages[0] = pStash->pPage; 1140 offPage0 = pStash->off; 1141 cbChunk = pStash->cb; 1142 cPages = 1; 1143 pStash->pPage = NULL; 1144 pStash->off = 0; 1145 pStash->cb = 0; 1146 if ( offPage0 + cbChunk < PAGE_SIZE 1147 || iov_iter_count(iter) == 0) { 1148 *poffPage0 = offPage0; 1149 *pcbChunk = cbChunk; 1150 *pcPages = cPages; 1151 return 0; 1152 } 1153 cMaxPages -= 1; 1154 } else { 1155 # if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) 1156 /* 1157 * Copy out our starting point to assist rewinding. 1158 */ 1159 pStash->offFromEnd = iov_iter_count(iter); 1160 pStash->Copy = *iter; 1161 # endif 1162 } 1163 1164 /* 1165 * Get pages segment by segment. 1166 */ 1167 do { 1168 /* 1169 * Make a special case of the first time thru here, since that's 1170 * the most typical scenario. 1171 */ 1172 ssize_t cbSegRet; 1173 if (cPages == 0) { 1174 cbSegRet = iov_iter_get_pages(iter, papPages, iov_iter_count(iter), cMaxPages, &offPage0); 1175 if (cbSegRet > 0) { 1176 iov_iter_advance(iter, cbSegRet); 1177 cbChunk = (size_t)cbSegRet; 1178 cPages = RT_ALIGN_Z(offPage0 + cbSegRet, PAGE_SIZE) >> PAGE_SHIFT; 1179 cMaxPages -= cPages; 1180 if ( cMaxPages == 0 1181 || ((offPage0 + (size_t)cbSegRet) & PAGE_OFFSET_MASK)) 1182 break; 1183 } else { 1184 AssertStmt(cbSegRet < 0, cbSegRet = -EFAULT); 1185 rc = (int)cbSegRet; 1186 break; 1187 } 1188 } else { 1189 /* 1190 * Probe first page of new segment to check that we've got a zero offset and 1191 * can continue on the current chunk. Stash the page if the offset isn't zero. 1192 */ 1193 size_t offPgProbe; 1194 size_t cbSeg = iov_iter_single_seg_count(iter); 1195 while (!cbSeg) { 1196 iov_iter_advance(iter, 0); 1197 cbSeg = iov_iter_single_seg_count(iter); 1198 } 1199 cbSegRet = iov_iter_get_pages(iter, &papPages[cPages], iov_iter_count(iter), 1, &offPgProbe); 1200 if (cbSegRet > 0) { 1201 iov_iter_advance(iter, cbSegRet); /** @todo maybe not do this if we stash the page? */ 1202 Assert(cbSegRet <= PAGE_SIZE); 1203 if (offPgProbe == 0) { 1204 cbChunk += cbSegRet; 1205 cPages += 1; 1206 cMaxPages -= 1; 1207 if ( cMaxPages == 0 1208 || cbSegRet != PAGE_SIZE) 1209 break; 1210 1211 /* 1212 * Get the rest of the segment (if anything remaining). 1213 */ 1214 cbSeg -= cbSegRet; 1215 if (cbSeg > 0) { 1216 cbSegRet = iov_iter_get_pages(iter, &papPages[cPages], iov_iter_count(iter), cMaxPages, &offPgProbe); 1217 if (cbSegRet > 0) { 1218 size_t const cSegsRet = RT_ALIGN_Z((size_t)cbSegRet, PAGE_SIZE) >> PAGE_SHIFT; 1219 Assert(offPgProbe == 0); 1220 iov_iter_advance(iter, cbSegRet); 1221 cPages += cSegsRet; 1222 cMaxPages -= cSegsRet; 1223 cbChunk += cbSegRet; 1224 if ( cMaxPages == 0 1225 || ((size_t)cbSegRet & PAGE_OFFSET_MASK)) 1226 break; 1227 } else { 1228 AssertStmt(cbSegRet < 0, cbSegRet = -EFAULT); 1229 rc = (int)cbSegRet; 1230 break; 1231 } 1232 } 1233 } else { 1234 /* The segment didn't start at a page boundrary, so stash it for 1235 the next round: */ 1236 Assert(papPages[cPages]); 1237 pStash->pPage = papPages[cPages]; 1238 pStash->off = offPage0; 1239 pStash->cb = cbSegRet; 1240 break; 1241 } 1242 } else { 1243 AssertStmt(cbSegRet < 0, cbSegRet = -EFAULT); 1244 rc = (int)cbSegRet; 1245 break; 1246 } 1247 } 1248 Assert(cMaxPages > 0); 1249 } while (iov_iter_count(iter) > 0); 1250 1251 } else { 1252 /* 1253 * The silly iov_iter_get_pages_alloc() function doesn't handle KVECs, 1254 * so everyone needs to do that by themselves. 1255 * 1256 * Note! Fixes here may apply to rtR0MemObjNativeLockKernel() 1257 * and vbsf_lock_user_pages_failed_check_kernel() as well. 1258 */ 1259 # if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) 1260 pStash->offFromEnd = iov_iter_count(iter); 1261 pStash->Copy = *iter; 1262 # endif 1263 do { 1264 uint8_t *pbBuf; 1265 size_t offStart; 1266 size_t cPgSeg; 1267 1268 size_t cbSeg = iov_iter_single_seg_count(iter); 1269 while (!cbSeg) { 1270 iov_iter_advance(iter, 0); 1271 cbSeg = iov_iter_single_seg_count(iter); 1272 } 1273 1274 # if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) 1275 pbBuf = iter->kvec->iov_base + iter->iov_offset; 1276 # else 1277 pbBuf = iter->iov->iov_base + iter->iov_offset; 1278 # endif 1279 offStart = (uintptr_t)pbBuf & PAGE_OFFSET_MASK; 1280 if (!cPages) 1281 offPage0 = offStart; 1282 else if (offStart) 1283 break; 1284 1285 cPgSeg = RT_ALIGN_Z(cbSeg, PAGE_SIZE) >> PAGE_SHIFT; 1286 if (cPgSeg > cMaxPages) { 1287 cPgSeg = cMaxPages; 1288 cbSeg = (cPgSeg << PAGE_SHIFT) - offStart; 1289 } 1290 1291 rc = vbsf_lock_kernel_pages(pbBuf, fWrite, cPgSeg, &papPages[cPages]); 1292 if (rc == 0) { 1293 iov_iter_advance(iter, cbSeg); 1294 cbChunk += cbSeg; 1295 cPages += cPgSeg; 1296 cMaxPages -= cPgSeg; 1297 if ( cMaxPages == 0 1298 || ((offStart + cbSeg) & PAGE_OFFSET_MASK) != 0) 1299 break; 1300 } else 1301 break; 1302 } while (iov_iter_count(iter) > 0); 1303 } 1304 1305 /* 1306 * Clean up if we failed; set return values. 1307 */ 1308 if (rc == 0) { 1309 /* likely */ 1310 } else { 1311 if (cPages > 0) 1312 vbsf_iter_unlock_pages(iter, papPages, cPages, false /*fSetDirty*/); 1313 offPage0 = cbChunk = cPages = 0; 1314 } 1315 *poffPage0 = offPage0; 1316 *pcbChunk = cbChunk; 1317 *pcPages = cPages; 1318 return rc; 1319 } 1320 1321 1322 /** 1323 * Rewinds the I/O vector. 1324 */ 1325 static bool vbsf_iter_rewind(struct iov_iter *iter, struct vbsf_iter_stash *pStash, size_t cbToRewind, size_t cbChunk) 1326 { 1327 size_t cbExtra; 1328 if (!pStash->pPage) { 1329 cbExtra = 0; 1330 } else { 1331 cbExtra = pStash->cb; 1332 vbsf_put_page(pStash->pPage); 1333 pStash->pPage = NULL; 1334 pStash->cb = 0; 1335 pStash->off = 0; 1336 } 1337 1338 # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) 1339 iov_iter_revert(iter, cbToRewind + cbExtra); 1340 return true; 1341 # else 1342 /** @todo impl this */ 1343 return false; 1344 # endif 1345 } 1346 1347 1348 /** 1349 * Cleans up the page locking stash. 1350 */ 1351 DECLINLINE(void) vbsf_iter_cleanup_stash(struct iov_iter *iter, struct vbsf_iter_stash *pStash) 1352 { 1353 if (pStash->pPage) 1354 vbsf_iter_rewind(iter, pStash, 0, 0); 1355 } 1356 1357 1358 /** 1359 * Calculates the longest span of pages we could transfer to the host in a 1360 * single request. 1361 * 1362 * @returns Page count, non-zero. 1363 * @param iter The I/O vector iterator to inspect. 1364 */ 1365 static size_t vbsf_iter_max_span_of_pages(struct iov_iter *iter) 1366 { 1367 size_t cPages; 1368 if (iter->type & (ITER_IOVEC | ITER_KVEC)) { 1369 const struct iovec *pCurIov = iter->iov; 1370 size_t cLeft = iter->nr_segs; 1371 size_t cPagesSpan = 0; 1372 1373 AssertCompileMembersSameSizeAndOffset(struct iovec, iov_base, struct kvec, iov_base); 1374 AssertCompileMembersSameSizeAndOffset(struct iovec, iov_len, struct kvec, iov_len); 1375 AssertCompile(sizeof(struct iovec) == sizeof(struct kvec)); 1376 1377 cPages = 1; 1378 AssertReturn(cLeft > 0, cPages); 1379 1380 /* Special case: segment offset. */ 1381 if (iter->iov_offset > 0) { 1382 if (iter->iov_offset < pCurIov->iov_len) { 1383 size_t const cbSegLeft = pCurIov->iov_len - iter->iov_offset; 1384 size_t const offPage0 = ((uintptr_t)pCurIov->iov_base + iter->iov_offset) & PAGE_OFFSET_MASK; 1385 cPages = cPagesSpan = RT_ALIGN_Z(offPage0 + cbSegLeft, PAGE_SIZE) >> PAGE_SHIFT; 1386 if ((offPage0 + cbSegLeft) & PAGE_OFFSET_MASK) 1387 cPagesSpan = 0; 1388 } 1389 pCurIov++; 1390 cLeft--; 1391 } 1392 1393 /* Full segments. */ 1394 while (cLeft-- > 0) { 1395 if (pCurIov->iov_len > 0) { 1396 size_t const offPage0 = (uintptr_t)pCurIov->iov_base & PAGE_OFFSET_MASK; 1397 if (offPage0 == 0) { 1398 if (!(pCurIov->iov_len & PAGE_OFFSET_MASK)) { 1399 cPagesSpan += pCurIov->iov_len >> PAGE_SHIFT; 1400 } else { 1401 cPagesSpan += RT_ALIGN_Z(pCurIov->iov_len, PAGE_SIZE) >> PAGE_SHIFT; 1402 if (cPagesSpan > cPages) 1403 cPages = cPagesSpan; 1404 cPagesSpan = 0; 1405 } 1406 } else { 1407 if (cPagesSpan > cPages) 1408 cPages = cPagesSpan; 1409 if (!((offPage0 + pCurIov->iov_len) & PAGE_OFFSET_MASK)) { 1410 cPagesSpan = pCurIov->iov_len >> PAGE_SHIFT; 1411 } else { 1412 cPagesSpan += RT_ALIGN_Z(offPage0 + pCurIov->iov_len, PAGE_SIZE) >> PAGE_SHIFT; 1413 if (cPagesSpan > cPages) 1414 cPages = cPagesSpan; 1415 cPagesSpan = 0; 1416 } 1417 } 1418 } 1419 pCurIov++; 1420 } 1421 if (cPagesSpan > cPages) 1422 cPages = cPagesSpan; 1423 } else { 1424 /* Won't bother with accurate counts for the next two types, just make 1425 some rough estimates (does pipes have segments?): */ 1426 size_t cSegs = iter->type & ITER_BVEC ? RT_MAX(1, iter->nr_segs) : 1; 1427 cPages = (iov_iter_count(iter) + (PAGE_SIZE * 2 - 2) * cSegs) >> PAGE_SHIFT; 1428 } 1429 return cPages; 1430 } 1431 1432 1433 /** 1434 * Worker for vbsf_reg_read_iter() that deals with larger reads using page 1435 * locking. 1436 */ 1437 static ssize_t vbsf_reg_read_iter_locking(struct kiocb *kio, struct iov_iter *iter, size_t cbToRead, 1438 struct vbsf_super_info *sf_g, struct vbsf_reg_info *sf_r) 1439 { 1440 /* 1441 * Estimate how many pages we may possible submit in a single request so 1442 * that we can allocate matching request buffer and page array. 1443 */ 1444 struct page *apPagesStack[16]; 1445 struct page **papPages = &apPagesStack[0]; 1446 struct page **papPagesFree = NULL; 1447 VBOXSFREADPGLSTREQ *pReq; 1448 ssize_t cbRet = 0; 1449 size_t cMaxPages = vbsf_iter_max_span_of_pages(iter); 1450 cMaxPages = RT_MIN(RT_MAX(sf_g->cMaxIoPages, 2), cMaxPages); 1451 1452 pReq = (VBOXSFREADPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFREADPGLSTREQ, PgLst.aPages[cMaxPages])); 1453 while (!pReq && cMaxPages > 4) { 1454 cMaxPages /= 2; 1455 pReq = (VBOXSFREADPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFREADPGLSTREQ, PgLst.aPages[cMaxPages])); 1456 } 1457 if (pReq && cMaxPages > RT_ELEMENTS(apPagesStack)) 1458 papPagesFree = papPages = kmalloc(cMaxPages * sizeof(sizeof(papPages[0])), GFP_KERNEL); 1459 if (pReq && papPages) { 1460 1461 /* 1462 * The read loop. 1463 */ 1464 struct vbsf_iter_stash Stash = VBSF_ITER_STASH_INITIALIZER; 1465 do { 1466 /* 1467 * Grab as many pages as we can. This means that if adjacent 1468 * segments both starts and ends at a page boundrary, we can 1469 * do them both in the same transfer from the host. 1470 */ 1471 size_t cPages = 0; 1472 size_t cbChunk = 0; 1473 size_t offPage0 = 0; 1474 int rc = vbsf_iter_lock_pages(iter, true /*fWrite*/, &Stash, cMaxPages, papPages, &cPages, &offPage0, &cbChunk); 1475 if (rc == 0) { 1476 size_t iPage = cPages; 1477 while (iPage-- > 0) 1478 pReq->PgLst.aPages[iPage] = page_to_phys(papPages[iPage]); 1479 pReq->PgLst.offFirstPage = (uint16_t)offPage0; 1480 AssertStmt(cbChunk <= cbToRead, cbChunk = cbToRead); 1481 } else { 1482 cbRet = rc; 1483 break; 1484 } 1485 1486 /* 1487 * Issue the request and unlock the pages. 1488 */ 1489 rc = VbglR0SfHostReqReadPgLst(sf_g->map.root, pReq, sf_r->Handle.hHost, kio->ki_pos, cbChunk, cPages); 1490 SFLOGFLOW(("vbsf_reg_read_iter_locking: VbglR0SfHostReqReadPgLst -> %d (cbActual=%#x cbChunk=%#zx of %#zx cPages=%#zx offPage0=%#x\n", 1491 rc, pReq->Parms.cb32Read.u.value32, cbChunk, cbToRead, cPages, offPage0)); 1492 1493 vbsf_iter_unlock_pages(iter, papPages, cPages, true /*fSetDirty*/); 1494 1495 if (RT_SUCCESS(rc)) { 1496 /* 1497 * Success, advance position and buffer. 1498 */ 1499 uint32_t cbActual = pReq->Parms.cb32Read.u.value32; 1500 AssertStmt(cbActual <= cbChunk, cbActual = cbChunk); 1501 cbRet += cbActual; 1502 kio->ki_pos += cbActual; 1503 cbToRead -= cbActual; 1504 1505 /* 1506 * Are we done already? 1507 */ 1508 if (!cbToRead) 1509 break; 1510 if (cbActual < cbChunk) { /* We ASSUME end-of-file here. */ 1511 if (vbsf_iter_rewind(iter, &Stash, cbChunk - cbActual, cbActual)) 1512 iov_iter_truncate(iter, 0); 1513 break; 1514 } 1515 } else { 1516 /* 1517 * Try rewind the iter structure. 1518 */ 1519 bool const fRewindOkay = vbsf_iter_rewind(iter, &Stash, cbChunk, cbChunk); 1520 if (rc == VERR_NO_MEMORY && cMaxPages > 4 && fRewindOkay) { 1521 /* 1522 * The host probably doesn't have enough heap to handle the 1523 * request, reduce the page count and retry. 1524 */ 1525 cMaxPages /= 4; 1526 Assert(cMaxPages > 0); 1527 } else { 1528 /* 1529 * If we've successfully read stuff, return it rather than 1530 * the error. (Not sure if this is such a great idea...) 1531 */ 1532 if (cbRet <= 0) 1533 cbRet = -EPROTO; 1534 break; 1535 } 1536 } 1537 } while (cbToRead > 0); 1538 1539 vbsf_iter_cleanup_stash(iter, &Stash); 1540 } 1541 else 1542 cbRet = -ENOMEM; 1543 if (papPagesFree) 1544 kfree(papPages); 1545 if (pReq) 1546 VbglR0PhysHeapFree(pReq); 1547 SFLOGFLOW(("vbsf_reg_read_iter_locking: returns %#zx (%zd)\n", cbRet, cbRet)); 1548 return cbRet; 1549 } 1550 1551 1552 /** 1553 * Read into I/O vector iterator. 1554 * 1555 * @returns Number of bytes read on success, negative errno on error. 1556 * @param kio The kernel I/O control block (or something like that). 1557 * @param iter The I/O vector iterator describing the buffer. 1558 */ 1559 static ssize_t vbsf_reg_read_iter(struct kiocb *kio, struct iov_iter *iter) 1560 { 1561 size_t cbToRead = iov_iter_count(iter); 1562 struct inode *inode = VBSF_GET_F_DENTRY(kio->ki_filp)->d_inode; 1563 struct address_space *mapping = inode->i_mapping; 1564 1565 struct vbsf_reg_info *sf_r = kio->ki_filp->private_data; 1566 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb); 1567 1568 SFLOGFLOW(("vbsf_reg_read_iter: inode=%p file=%p size=%#zx off=%#llx type=%#x\n", 1569 inode, kio->ki_filp, cbToRead, kio->ki_pos, iter->type)); 1570 AssertReturn(S_ISREG(inode->i_mode), -EINVAL); 1571 1572 /* 1573 * Do we have anything at all to do here? 1574 */ 1575 if (!cbToRead) 1576 return 0; 1577 1578 /* 1579 * If there is a mapping and O_DIRECT isn't in effect, we must at a 1580 * heed dirty pages in the mapping and read from them. For simplicity 1581 * though, we just do page cache reading when there are writable 1582 * mappings around with any kind of pages loaded. 1583 */ 1584 if (vbsf_should_use_cached_read(kio->ki_filp, mapping, sf_g)) 1585 return generic_file_read_iter(kio, iter); 1586 1587 /* 1588 * Now now we reject async I/O requests. 1589 */ 1590 if (!is_sync_kiocb(kio)) { 1591 SFLOGFLOW(("vbsf_reg_read_iter: async I/O not yet supported\n")); /** @todo extend FsPerf with AIO tests. */ 1592 return -EOPNOTSUPP; 1593 } 1594 1595 /* 1596 * For small requests, try use an embedded buffer provided we get a heap block 1597 * that does not cross page boundraries (see host code). 1598 */ 1599 if (cbToRead <= PAGE_SIZE / 4 * 3 - RT_UOFFSETOF(VBOXSFREADEMBEDDEDREQ, abData[0]) /* see allocator */) { 1600 uint32_t const cbReq = RT_UOFFSETOF(VBOXSFREADEMBEDDEDREQ, abData[0]) + cbToRead; 1601 VBOXSFREADEMBEDDEDREQ *pReq = (VBOXSFREADEMBEDDEDREQ *)VbglR0PhysHeapAlloc(cbReq); 1602 if (pReq) { 1603 if ((PAGE_SIZE - ((uintptr_t)pReq & PAGE_OFFSET_MASK)) >= cbReq) { 1604 ssize_t cbRet; 1605 int vrc = VbglR0SfHostReqReadEmbedded(sf_g->map.root, pReq, sf_r->Handle.hHost, kio->ki_pos, (uint32_t)cbToRead); 1606 if (RT_SUCCESS(vrc)) { 1607 cbRet = pReq->Parms.cb32Read.u.value32; 1608 AssertStmt(cbRet <= (ssize_t)cbToRead, cbRet = cbToRead); 1609 if (copy_to_iter(pReq->abData, cbRet, iter) == cbRet) { 1610 kio->ki_pos += cbRet; 1611 if (cbRet < cbToRead) 1612 iov_iter_truncate(iter, 0); 1613 } else 1614 cbRet = -EFAULT; 1615 } else 1616 cbRet = -EPROTO; 1617 VbglR0PhysHeapFree(pReq); 1618 SFLOGFLOW(("vbsf_reg_read_iter: returns %#zx (%zd)\n", cbRet, cbRet)); 1619 return cbRet; 1620 } 1621 VbglR0PhysHeapFree(pReq); 1622 } 1623 } 1624 1625 /* 1626 * Otherwise do the page locking thing. 1627 */ 1628 return vbsf_reg_read_iter_locking(kio, iter, cbToRead, sf_g, sf_r); 1629 } 1630 1631 1632 static ssize_t vbsf_reg_write_iter(struct kiocb *kio, struct iov_iter *iter) 1633 { 1634 SFLOGFLOW(("vbsf_reg_write_iter: -> EINVAL\n")); 1635 return -EINVAL; 1636 } 1637 1638 #endif /* >= 3.16.0 */ 1046 1639 1047 1640 /** … … 1336 1929 */ 1337 1930 struct file_operations vbsf_reg_fops = { 1338 .read = vbsf_reg_read, 1339 .open = vbsf_reg_open, 1340 .write = vbsf_reg_write, 1341 .release = vbsf_reg_release, 1342 .mmap = generic_file_mmap, 1931 .open = vbsf_reg_open, 1932 .read = vbsf_reg_read, 1933 .write = vbsf_reg_write, 1934 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) 1935 .read_iter = vbsf_reg_read_iter, 1936 .write_iter = vbsf_reg_write_iter, 1937 #endif 1938 .release = vbsf_reg_release, 1939 .mmap = generic_file_mmap, 1343 1940 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) 1344 1941 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) … … 1348 1945 .splice_read = vbsf_splice_read, 1349 1946 # else 1350 .sendfile = generic_file_sendfile,1947 .sendfile = generic_file_sendfile, 1351 1948 # endif 1352 .aio_read = generic_file_aio_read,1353 .aio_write = generic_file_aio_write,1949 .aio_read = generic_file_aio_read, 1950 .aio_write = generic_file_aio_write, 1354 1951 # endif 1355 1952 #endif 1356 .llseek = vbsf_reg_llseek,1357 .fsync = vbsf_reg_fsync,1953 .llseek = vbsf_reg_llseek, 1954 .fsync = vbsf_reg_fsync, 1358 1955 }; 1359 1956 -
trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.c
r77542 r77626 120 120 happens, which isn't too efficient. */ 121 121 sf_g->cMaxIoPages = RT_MIN(_16K / sizeof(RTGCPHYS64) /* => 8MB buffer */, 122 VMMDEV_MAX_HGCM_DATA_SIZE >> PAGE_SHIFT);122 VMMDEV_MAX_HGCM_DATA_SIZE >> PAGE_SHIFT); 123 123 if ( (unsigned)info->length >= sizeof(struct vbsf_mount_info_new) 124 && info->cMaxIoPages !=0) {124 && info->cMaxIoPages > 0) { 125 125 if (info->cMaxIoPages <= VMMDEV_MAX_HGCM_DATA_SIZE >> PAGE_SHIFT) 126 sf_g->cMaxIoPages = info->cMaxIoPages;126 sf_g->cMaxIoPages = RT_MAX(info->cMaxIoPages, 2); /* read_iter/write_iter requires a minimum of 2. */ 127 127 else 128 128 printk(KERN_WARNING "vboxsf: max I/O page count (%#x) is out of range, using default (%#x) instead.\n", 129 129 info->cMaxIoPages, sf_g->cMaxIoPages); 130 130 } 131 131 }
Note:
See TracChangeset
for help on using the changeset viewer.