Changeset 77539 in vbox
- Timestamp:
- Mar 2, 2019 8:47:13 PM (6 years ago)
- Location:
- trunk/src/VBox/Additions/linux/sharedfolders
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/linux/sharedfolders/dirops.c
r77538 r77539 34 34 35 35 /** 36 * Reads or re-reads a directory. 37 * 38 * @note As suggested a couple of other places, we should probably stop 39 * reading in the whole directory on open. 40 * 41 * @todo merge with caller now that the VBSF_BUFFER_DIRS code is gonne. 42 */ 43 static int vbsf_dir_open_worker(struct dentry *pDirEntry, struct inode *pInode, struct vbsf_inode_info *sf_i, 44 struct vbsf_dir_info *sf_d, struct vbsf_super_info *sf_g, const char *pszCaller) 45 { 46 union SfDirOpenCloseReq 47 { 48 VBOXSFCREATEREQ Create; 49 VBOXSFCLOSEREQ Close; 50 } *pReq; 51 int err; 52 53 pReq = (union SfDirOpenCloseReq *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + sf_i->path->u16Size); 54 if (pReq) { 55 int rc; 56 57 memcpy(&pReq->Create.StrPath, sf_i->path, SHFLSTRING_HEADER_SIZE + sf_i->path->u16Size); 58 RT_ZERO(pReq->Create.CreateParms); 59 pReq->Create.CreateParms.Handle = SHFL_HANDLE_NIL; 60 pReq->Create.CreateParms.CreateFlags = SHFL_CF_DIRECTORY 61 | SHFL_CF_ACT_OPEN_IF_EXISTS 62 | SHFL_CF_ACT_FAIL_IF_NEW 63 | SHFL_CF_ACCESS_READ; 64 65 LogFunc(("calling VbglR0SfHostReqCreate on folder %s, flags %#x [caller: %s]\n", 66 sf_i->path->String.utf8, pReq->Create.CreateParms.CreateFlags, pszCaller)); 67 rc = VbglR0SfHostReqCreate(sf_g->map.root, &pReq->Create); 68 if (RT_SUCCESS(rc)) { 69 if (pReq->Create.CreateParms.Result == SHFL_FILE_EXISTS) { 70 Assert(pReq->Create.CreateParms.Handle != SHFL_HANDLE_NIL); 71 72 /* 73 * Update the inode info with fresh stats and increase the TTL for the 74 * dentry cache chain that got us here. 75 */ 76 vbsf_update_inode(pInode, sf_i, &pReq->Create.CreateParms.Info, sf_g, true /*fLocked*/ /** @todo inode locking */); 77 vbsf_dentry_chain_increase_ttl(pDirEntry); 78 79 sf_d->Handle.hHost = pReq->Create.CreateParms.Handle; 80 sf_d->Handle.cRefs = 1; 81 sf_d->Handle.fFlags = VBSF_HANDLE_F_READ | VBSF_HANDLE_F_DIR | VBSF_HANDLE_F_MAGIC; 82 vbsf_handle_append(sf_i, &sf_d->Handle); 83 84 VbglR0PhysHeapFree(pReq); 85 return 0; 86 } 87 88 /* 89 * Directory does not exist, so we probably got some invalid 90 * dir cache and inode info. 91 */ 92 /** @todo do more to invalidate dentry and inode here. */ 93 vbsf_dentry_set_update_jiffies(pDirEntry, jiffies + INT_MAX / 2); 94 sf_i->force_restat = true; 95 err = -ENOENT; 96 97 AssertCompile(RTASSERT_OFFSET_OF(VBOXSFCREATEREQ, CreateParms.Handle) > sizeof(VBOXSFCLOSEREQ)); /* no aliasing issues */ 98 if (pReq->Create.CreateParms.Handle != SHFL_HANDLE_NIL) { 99 rc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, pReq->Create.CreateParms.Handle); 100 if (RT_FAILURE(rc)) 101 LogFunc(("VbglR0SfHostReqCloseSimple(%s) after err=%d failed rc=%Rrc caller=%s\n", 102 sf_i->path->String.utf8, err, rc, pszCaller)); 103 } 104 } else 105 err = -EPERM; 106 107 VbglR0PhysHeapFree(pReq); 108 } else { 109 LogRelMaxFunc(64, ("failed to allocate %zu bytes for '%s' [caller: %s]\n", 110 RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + sf_i->path->u16Size, 111 sf_i->path->String.ach, pszCaller)); 112 err = -ENOMEM; 113 } 114 return err; 115 } 116 117 /** 118 * Open a directory. Read the complete content into a buffer. 36 * Open a directory. 119 37 * 120 38 * @param inode inode … … 141 59 sf_d = kmalloc(sizeof(*sf_d), GFP_KERNEL); 142 60 if (sf_d) { 61 VBOXSFCREATEREQ *pReq; 143 62 RT_ZERO(*sf_d); 144 63 sf_d->u32Magic = VBSF_DIR_INFO_MAGIC; 64 sema_init(&sf_d->Lock, 1); 145 65 146 66 /* 147 67 * Try open the directory. 148 68 */ 149 rc = vbsf_dir_open_worker(dentry, inode, sf_i, sf_d, sf_g, "vbsf_dir_open"); 150 if (!rc) 151 file->private_data = sf_d; 152 else { 153 sf_d->u32Magic = VBSF_DIR_INFO_MAGIC_DEAD; 154 kfree(sf_d); 155 } 69 pReq = (VBOXSFCREATEREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + sf_i->path->u16Size); 70 if (pReq) { 71 memcpy(&pReq->StrPath, sf_i->path, SHFLSTRING_HEADER_SIZE + sf_i->path->u16Size); 72 RT_ZERO(pReq->CreateParms); 73 pReq->CreateParms.Handle = SHFL_HANDLE_NIL; 74 pReq->CreateParms.CreateFlags = SHFL_CF_DIRECTORY 75 | SHFL_CF_ACT_OPEN_IF_EXISTS 76 | SHFL_CF_ACT_FAIL_IF_NEW 77 | SHFL_CF_ACCESS_READ; 78 79 LogFunc(("calling VbglR0SfHostReqCreate on folder %s, flags %#x\n", 80 sf_i->path->String.utf8, pReq->CreateParms.CreateFlags)); 81 rc = VbglR0SfHostReqCreate(sf_g->map.root, pReq); 82 if (RT_SUCCESS(rc)) { 83 if (pReq->CreateParms.Result == SHFL_FILE_EXISTS) { 84 Assert(pReq->CreateParms.Handle != SHFL_HANDLE_NIL); 85 86 /* 87 * Update the inode info with fresh stats and increase the TTL for the 88 * dentry cache chain that got us here. 89 */ 90 vbsf_update_inode(inode, sf_i, &pReq->CreateParms.Info, sf_g, true /*fLocked*/ /** @todo inode locking */); 91 vbsf_dentry_chain_increase_ttl(dentry); 92 93 sf_d->Handle.hHost = pReq->CreateParms.Handle; 94 sf_d->Handle.cRefs = 1; 95 sf_d->Handle.fFlags = VBSF_HANDLE_F_READ | VBSF_HANDLE_F_DIR | VBSF_HANDLE_F_MAGIC; 96 vbsf_handle_append(sf_i, &sf_d->Handle); 97 98 file->private_data = sf_d; 99 VbglR0PhysHeapFree(pReq); 100 return 0; 101 102 } 103 Assert(pReq->CreateParms.Handle == SHFL_HANDLE_NIL); 104 105 /* 106 * Directory does not exist, so we probably got some invalid 107 * dir cache and inode info. 108 */ 109 /** @todo do more to invalidate dentry and inode here. */ 110 vbsf_dentry_set_update_jiffies(dentry, jiffies + INT_MAX / 2); 111 sf_i->force_restat = true; 112 rc = -ENOENT; 113 } else 114 rc = -EPERM; 115 VbglR0PhysHeapFree(pReq); 116 } else { 117 LogRelMaxFunc(64, ("failed to allocate %zu bytes for '%s'\n", 118 RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + sf_i->path->u16Size, sf_i->path->String.ach)); 119 rc = -ENOMEM; 120 } 121 sf_d->u32Magic = VBSF_DIR_INFO_MAGIC_DEAD; 122 kfree(sf_d); 156 123 } else 157 124 rc = -ENOMEM; 158 125 return rc; 159 126 } 127 160 128 161 129 /** … … 355 323 struct vbsf_dir_info *sf_d = (struct vbsf_dir_info *)dir->private_data; 356 324 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(VBSF_GET_F_DENTRY(dir)->d_sb); 325 int rc; 326 327 /* 328 * Lock the directory info structures. 329 */ 330 if (RT_LIKELY(down_interruptible(&sf_d->Lock) == 0)) { 331 /* likely */ 332 } else 333 return -ERESTARTSYS; 357 334 358 335 /* … … 362 339 /* likely */ 363 340 } else { 364 int rc;365 366 341 /* Restart the search if iPos is lower than the current buffer position. */ 367 342 loff_t offCurEntry = sf_d->offPos; … … 370 345 if (rc == 0) 371 346 offCurEntry = 0; 372 else 347 else { 348 up(&sf_d->Lock); 373 349 return rc; 350 } 374 351 } 375 352 … … 383 360 sf_d->cEntriesLeft = 0; 384 361 rc = vbsf_dir_read_more(sf_d, sf_g, false /*fRestart*/); 385 if (rc != 0 || sf_d->cEntriesLeft == 0) 362 if (rc != 0 || sf_d->cEntriesLeft == 0) { 363 up(&sf_d->Lock); 386 364 return rc; 365 } 387 366 } else { 388 367 do … … 411 390 if (dir_emit_dot(dir, ctx)) 412 391 dir->f_pos = ctx->pos = sf_d->offPos = offPos = 1; 413 else 392 else { 393 up(&sf_d->Lock); 414 394 return 0; 395 } 415 396 } 416 397 if (offPos == 1) { 417 398 if (dir_emit_dotdot(dir, ctx)) 418 399 dir->f_pos = ctx->pos = sf_d->offPos = offPos = 2; 419 else 400 else { 401 up(&sf_d->Lock); 420 402 return 0; 403 } 421 404 } 422 405 #else 423 406 if (offPos == 0) { 424 intrc = filldir(opaque, ".", 1, 0, VBSF_GET_F_DENTRY(dir)->d_inode->i_ino, DT_DIR);407 rc = filldir(opaque, ".", 1, 0, VBSF_GET_F_DENTRY(dir)->d_inode->i_ino, DT_DIR); 425 408 if (!rc) 426 409 dir->f_pos = sf_d->offPos = offPos = 1; 427 else 410 else { 411 up(&sf_d->Lock); 428 412 return 0; 413 } 429 414 } 430 415 if (offPos == 1) { 431 416 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 5) 432 intrc = filldir(opaque, "..", 2, 1, parent_ino(VBSF_GET_F_DENTRY(dir)), DT_DIR);417 rc = filldir(opaque, "..", 2, 1, parent_ino(VBSF_GET_F_DENTRY(dir)), DT_DIR); 433 418 # else 434 intrc = filldir(opaque, "..", 2, 1, VBSF_GET_F_DENTRY(dir)->d_parent->d_inode->i_ino, DT_DIR);419 rc = filldir(opaque, "..", 2, 1, VBSF_GET_F_DENTRY(dir)->d_parent->d_inode->i_ino, DT_DIR); 435 420 # endif 436 421 if (!rc) 437 422 dir->f_pos = sf_d->offPos = offPos = 2; 438 else 423 else { 424 up(&sf_d->Lock); 439 425 return 0; 426 } 440 427 } 441 428 #endif … … 456 443 uint32_t cEntriesLeft = sf_d->cEntriesLeft; 457 444 if (!cEntriesLeft) { 458 intrc = vbsf_dir_read_more(sf_d, sf_g, false /*fRestart*/);445 rc = vbsf_dir_read_more(sf_d, sf_g, false /*fRestart*/); 459 446 if (rc == 0) { 460 447 cEntriesLeft = sf_d->cEntriesLeft; 461 if (!cEntriesLeft) 448 if (!cEntriesLeft) { 449 up(&sf_d->Lock); 462 450 return 0; 451 } 463 452 cbValid = sf_d->cbValid; 464 } 465 else453 } else { 454 up(&sf_d->Lock); 466 455 return rc; 456 } 467 457 } 468 458 … … 518 508 sf_d->pEntry = pEntry; 519 509 sf_d->offPos = offPos; 510 up(&sf_d->Lock); 520 511 return 0; 521 512 } … … 547 538 .open = vbsf_dir_open, 548 539 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) 549 .iterate = vbsf_dir_iterate, /** @todo Consider .iterate_shared (shared vs exclusive inode lock) here. Need to consider 550 * whether struct vbsf_dir_info is safe in multithreaded apps doing readdir in parallel on 551 * the same handle. */ 540 .iterate_shared = vbsf_dir_iterate, 552 541 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) 553 542 .iterate = vbsf_dir_iterate, -
trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.h
r77538 r77539 273 273 * @note Must be first! */ 274 274 struct vbsf_handle Handle; 275 /** Semaphore protecting everything below. */ 276 struct semaphore Lock; 275 277 /** A magic number (VBSF_DIR_INFO_MAGIC). */ 276 278 uint32_t u32Magic; … … 283 285 /** Number of entries left in the buffer. */ 284 286 uint32_t cEntriesLeft; 285 /** The position of the next entry. Incremented by one for each entry. 287 /** The position of the next entry. Incremented by one for each entry. */ 286 288 loff_t offPos; 287 289 /** The next entry. */
Note:
See TracChangeset
for help on using the changeset viewer.