Changeset 77526 in vbox
- Timestamp:
- Mar 1, 2019 12:15:29 PM (6 years ago)
- Location:
- trunk/src/VBox/Additions/linux/sharedfolders
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/linux/sharedfolders/dirops.c
r77525 r77526 40 40 */ 41 41 static int sf_dir_open_worker(struct vbsf_super_info *sf_g, struct sf_dir_info *sf_d, 42 42 struct sf_inode_info *sf_i, const char *pszCaller) 43 43 { 44 44 int rc; … … 46 46 union SfDirOpenCloseReq 47 47 { 48 49 48 VBOXSFCREATEREQ Create; 49 VBOXSFCLOSEREQ Close; 50 50 } *pReq; 51 51 SHFLCREATEPARMS *pCreateParms; 52 52 53 53 pReq = (union SfDirOpenCloseReq *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) 54 54 + sf_i->path->u16Size); 55 55 if (pReq) { 56 57 56 memcpy(&pReq->Create.StrPath, sf_i->path, SHFLSTRING_HEADER_SIZE + sf_i->path->u16Size); 57 pCreateParms = &pReq->Create.CreateParms; 58 58 } else { 59 60 61 62 59 LogRelMaxFunc(64, ("failed to allocate %zu bytes for '%s' [caller: %s]\n", 60 RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + sf_i->path->u16Size, 61 sf_i->path->String.ach, pszCaller)); 62 return -ENOMEM; 63 63 } 64 64 … … 66 66 pCreateParms->Handle = SHFL_HANDLE_NIL; 67 67 pCreateParms->CreateFlags = SHFL_CF_DIRECTORY 68 69 70 68 | SHFL_CF_ACT_OPEN_IF_EXISTS 69 | SHFL_CF_ACT_FAIL_IF_NEW 70 | SHFL_CF_ACCESS_READ; 71 71 72 72 LogFunc(("calling VbglR0SfHostReqCreate on folder %s, flags %#x [caller: %s]\n", 73 73 sf_i->path->String.utf8, pCreateParms->CreateFlags, pszCaller)); 74 74 rc = VbglR0SfHostReqCreate(sf_g->map.root, &pReq->Create); 75 75 if (RT_SUCCESS(rc)) { 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 76 if (pCreateParms->Result == SHFL_FILE_EXISTS) { 77 78 /** @todo We could refresh the inode information here since SHFL_FN_CREATE 79 * returns updated object information. */ 80 81 /** @todo Touch the dentries from here to the mount root since a successful 82 * open means that the whole path is valid. I believe CIFS does this. */ 83 84 /** @todo Reading all entries upon opening the directory doesn't seem like 85 * a good idea. */ 86 sf_dir_info_empty(sf_d); 87 err = sf_dir_read_all(sf_g, sf_i, sf_d, pCreateParms->Handle); 88 } else 89 err = -ENOENT; 90 91 AssertCompile(RTASSERT_OFFSET_OF(VBOXSFCREATEREQ, CreateParms.Handle) > sizeof(VBOXSFCLOSEREQ)); /* no aliasing issues */ 92 if (pCreateParms->Handle != SHFL_HANDLE_NIL) 93 { 94 rc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, pCreateParms->Handle); 95 if (RT_FAILURE(rc)) 96 LogFunc(("VbglR0SfHostReqCloseSimple(%s) after err=%d failed rc=%Rrc caller=%s\n", 97 sf_i->path->String.utf8, err, rc, pszCaller)); 98 } 99 99 } else 100 100 err = -EPERM; 101 101 102 102 VbglR0PhysHeapFree(pReq); … … 113 113 static int sf_dir_open(struct inode *inode, struct file *file) 114 114 { 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 115 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb); 116 struct sf_inode_info *sf_i = GET_INODE_INFO(inode); 117 struct sf_dir_info *sf_d; 118 int err; 119 120 TRACE(); 121 BUG_ON(!sf_g); 122 BUG_ON(!sf_i); 123 124 if (file->private_data) { 125 LogFunc(("called on already opened directory '%s'!\n", sf_i->path->String.ach)); 126 return 0; 127 } 128 129 sf_d = sf_dir_info_alloc(); 130 if (!sf_d) { 131 LogRelFunc(("could not allocate directory info for '%s'\n", sf_i->path->String.ach)); 132 return -ENOMEM; 133 } 134 135 err = sf_dir_open_worker(sf_g, sf_d, sf_i, "sf_dir_open"); 136 if (!err) 137 file->private_data = sf_d; 138 else 139 sf_dir_info_free(sf_d); 140 141 return err; 142 142 } 143 143 … … 153 153 static int sf_dir_release(struct inode *inode, struct file *file) 154 154 { 155 156 157 158 159 160 155 TRACE(); 156 157 if (file->private_data) 158 sf_dir_info_free(file->private_data); 159 160 return 0; 161 161 } 162 162 … … 168 168 static int sf_get_d_type(RTFMODE fMode) 169 169 { 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 170 int d_type; 171 switch (fMode & RTFS_TYPE_MASK) { 172 case RTFS_TYPE_FIFO: 173 d_type = DT_FIFO; 174 break; 175 case RTFS_TYPE_DEV_CHAR: 176 d_type = DT_CHR; 177 break; 178 case RTFS_TYPE_DIRECTORY: 179 d_type = DT_DIR; 180 break; 181 case RTFS_TYPE_DEV_BLOCK: 182 d_type = DT_BLK; 183 break; 184 case RTFS_TYPE_FILE: 185 d_type = DT_REG; 186 break; 187 case RTFS_TYPE_SYMLINK: 188 d_type = DT_LNK; 189 break; 190 case RTFS_TYPE_SOCKET: 191 d_type = DT_SOCK; 192 break; 193 case RTFS_TYPE_WHITEOUT: 194 d_type = DT_WHT; 195 break; 196 default: 197 d_type = DT_UNKNOWN; 198 break; 199 } 200 return d_type; 201 201 } 202 202 … … 208 208 static int sf_getdent(struct file *dir, char d_name[NAME_MAX], int *d_type) 209 209 { 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 210 loff_t cur; 211 struct vbsf_super_info *sf_g; 212 struct sf_dir_info *sf_d; 213 struct sf_inode_info *sf_i; 214 struct inode *inode; 215 struct list_head *pos, *list; 216 217 TRACE(); 218 219 inode = GET_F_DENTRY(dir)->d_inode; 220 sf_i = GET_INODE_INFO(inode); 221 sf_g = VBSF_GET_SUPER_INFO(inode->i_sb); 222 sf_d = dir->private_data; 223 224 BUG_ON(!sf_g); 225 BUG_ON(!sf_d); 226 BUG_ON(!sf_i); 227 228 if (sf_i->force_reread) { 229 int err = sf_dir_open_worker(sf_g, sf_d, sf_i, "sf_getdent"); 230 if (!err) { 231 sf_i->force_reread = 0; 232 } else { 233 if (err == -ENOENT) { 234 sf_dir_info_free(sf_d); 235 dir->private_data = NULL; 236 } 237 return err; 238 } 239 } 240 241 cur = 0; 242 list = &sf_d->info_list; 243 list_for_each(pos, list) { 244 struct sf_dir_buf *b; 245 SHFLDIRINFO *info; 246 loff_t i; 247 248 b = list_entry(pos, struct sf_dir_buf, head); 249 if (dir->f_pos >= cur + b->cEntries) { 250 cur += b->cEntries; 251 continue; 252 } 253 254 for (i = 0, info = b->buf; i < dir->f_pos - cur; ++i) { 255 size_t size; 256 257 size = offsetof(SHFLDIRINFO, name.String) 258 + info->name.u16Size; 259 info = (SHFLDIRINFO *)((uintptr_t)info + size); 260 } 261 262 *d_type = sf_get_d_type(info->Info.Attr.fMode); 263 264 return sf_nlscpy(sf_g, d_name, NAME_MAX, 265 info->name.String.utf8, info->name.u16Length); 266 } 267 268 return 1; 269 269 } 270 270 … … 298 298 #endif 299 299 { 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 300 TRACE(); 301 for (;;) { 302 int err; 303 ino_t fake_ino; 304 loff_t sanity; 305 char d_name[NAME_MAX]; 306 int d_type = DT_UNKNOWN; 307 308 err = sf_getdent(dir, d_name, &d_type); 309 switch (err) { 310 case 1: 311 return 0; 312 313 case 0: 314 break; 315 316 case -1: 317 default: 318 /* skip erroneous entry and proceed */ 319 LogFunc(("sf_getdent error %d\n", err)); 320 dir->f_pos += 1; 321 321 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) 322 323 #endif 324 325 326 327 322 ctx->pos += 1; 323 #endif 324 continue; 325 } 326 327 /* d_name now contains a valid entry name */ 328 328 329 329 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) 330 330 sanity = ctx->pos + 0xbeef; 331 331 #else 332 333 #endif 334 335 336 337 338 332 sanity = dir->f_pos + 0xbeef; 333 #endif 334 fake_ino = sanity; 335 if (sanity - fake_ino) { 336 LogRelFunc(("can not compute ino\n")); 337 return -EINVAL; 338 } 339 339 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) 340 341 342 343 340 if (!dir_emit(ctx, d_name, strlen(d_name), fake_ino, d_type)) { 341 LogFunc(("dir_emit failed\n")); 342 return 0; 343 } 344 344 #else 345 346 347 348 349 350 351 352 353 #endif 354 355 345 err = filldir(opaque, d_name, strlen(d_name), 346 dir->f_pos, fake_ino, d_type); 347 if (err) { 348 LogFunc(("filldir returned error %d\n", err)); 349 /* Rely on the fact that filldir returns error 350 only when it runs out of space in opaque */ 351 return 0; 352 } 353 #endif 354 355 dir->f_pos += 1; 356 356 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) 357 358 #endif 359 360 361 357 ctx->pos += 1; 358 #endif 359 } 360 361 BUG(); 362 362 } 363 363 364 364 struct file_operations sf_dir_fops = { 365 365 .open = sf_dir_open, 366 366 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) 367 367 .iterate = sf_dir_iterate, 368 368 #else 369 370 #endif 371 372 369 .readdir = sf_dir_read, 370 #endif 371 .release = sf_dir_release, 372 .read = generic_read_dir 373 373 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) 374 374 , .llseek = generic_file_llseek 375 375 #endif 376 376 }; … … 382 382 */ 383 383 static struct inode *sf_create_inode(struct inode *parent, struct dentry *dentry, PSHFLSTRING path, 384 385 { 386 387 388 389 390 391 384 PSHFLFSOBJINFO pObjInfo, struct vbsf_super_info *sf_g, bool fInstantiate) 385 { 386 /* 387 * Allocate memory for our additional inode info and create an inode. 388 */ 389 struct sf_inode_info *sf_new_i = (struct sf_inode_info *)kmalloc(sizeof(*sf_new_i), GFP_KERNEL); 390 if (sf_new_i) { 391 ino_t iNodeNo = iunique(parent->i_sb, 1); 392 392 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) 393 393 struct inode *pInode = iget_locked(parent->i_sb, iNodeNo); 394 394 #else 395 396 #endif 397 398 399 400 395 struct inode *pInode = iget(parent->i_sb, iNodeNo); 396 #endif 397 if (pInode) { 398 /* 399 * Initialize the two structures. 400 */ 401 401 #ifdef VBOX_STRICT 402 403 #endif 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 402 sf_new_i->u32Magic = SF_INODE_INFO_MAGIC; 403 #endif 404 sf_new_i->path = path; 405 sf_new_i->force_reread = 0; 406 sf_new_i->force_restat = 0; 407 sf_new_i->ts_up_to_date = jiffies; 408 RTListInit(&sf_new_i->HandleList); 409 sf_new_i->handle = SHFL_HANDLE_NIL; 410 411 SET_INODE_INFO(pInode, sf_new_i); 412 sf_init_inode(pInode, sf_new_i, pObjInfo, sf_g); 413 414 /* 415 * Before we unlock the new inode, we may need to call d_instantiate. 416 */ 417 if (fInstantiate) 418 d_instantiate(dentry, pInode); 419 419 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) 420 421 #endif 422 423 424 425 426 427 428 429 420 unlock_new_inode(pInode); 421 #endif 422 return pInode; 423 424 } 425 LogFunc(("iget failed\n")); 426 kfree(sf_new_i); 427 } else 428 LogRelFunc(("could not allocate memory for new inode info\n")); 429 return NULL; 430 430 } 431 431 … … 441 441 static struct dentry *sf_lookup(struct inode *parent, struct dentry *dentry 442 442 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) 443 443 , unsigned int flags 444 444 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) 445 446 #endif 447 )448 { 449 450 451 452 453 445 , struct nameidata *nd 446 #endif 447 ) 448 { 449 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(parent->i_sb); 450 struct sf_inode_info *sf_i = GET_INODE_INFO(parent); 451 SHFLSTRING *path; 452 struct dentry *dret; 453 int rc; 454 454 455 455 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) 456 456 SFLOGFLOW(("sf_lookup: parent=%p dentry=%p flags=%#x\n", parent, dentry, flags)); 457 457 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) 458 458 SFLOGFLOW(("sf_lookup: parent=%p dentry=%p nd=%p{.flags=%#x}\n", parent, dentry, nd, nd ? nd->flags : 0)); 459 459 #else 460 SFLOGFLOW(("sf_lookup: parent=%p dentry=%p\n", parent, dentry)); 461 #endif 462 463 Assert(sf_g); 464 Assert(sf_i && sf_i->u32Magic == SF_INODE_INFO_MAGIC); 465 466 /* 467 * Build the path. We'll associate the path with dret's inode on success. 468 */ 469 rc = sf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path); 470 if (rc == 0) { 471 /* 472 * Do a lookup on the host side. 473 */ 474 VBOXSFCREATEREQ *pReq = (VBOXSFCREATEREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq) + path->u16Size); 475 if (pReq) { 476 struct inode *pInode = NULL; 477 478 RT_ZERO(*pReq); 479 memcpy(&pReq->StrPath, path, SHFLSTRING_HEADER_SIZE + path->u16Size); 480 pReq->CreateParms.Handle = SHFL_HANDLE_NIL; 481 pReq->CreateParms.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW; 482 483 LogFunc(("Calling VbglR0SfHostReqCreate on %s\n", path->String.utf8)); 484 rc = VbglR0SfHostReqCreate(sf_g->map.root, pReq); 485 if (RT_SUCCESS(rc)) { 486 if (pReq->CreateParms.Result == SHFL_FILE_EXISTS) { 487 /* 488 * Create an inode for the result. Since this also confirms 489 * the existence of all parent dentries, we increase their TTL. 490 */ 491 pInode = sf_create_inode(parent, dentry, path, &pReq->CreateParms.Info, 492 sf_g, false /*fInstantiate*/); 493 if (rc == 0) { 494 path = NULL; /* given to the inode */ 495 dret = dentry; 496 } else 497 dret = (struct dentry *)ERR_PTR(-ENOMEM); 498 sf_dentry_chain_increase_parent_ttl(dentry); 499 } else if ( pReq->CreateParms.Result == SHFL_FILE_NOT_FOUND 500 || pReq->CreateParms.Result == SHFL_PATH_NOT_FOUND /*this probably should happen*/) { 501 dret = dentry; 502 } else { 503 AssertMsgFailed(("%d\n", pReq->CreateParms.Result)); 504 dret = (struct dentry *)ERR_PTR(-EPROTO); 505 } 506 } else if (rc == VERR_INVALID_NAME) { 507 dret = dentry; /* this can happen for names like 'foo*' on a Windows host */ 508 } else { 509 LogFunc(("VbglR0SfHostReqCreate failed on %s: %Rrc\n", path->String.utf8, rc)); 510 dret = (struct dentry *)ERR_PTR(-EPROTO); 511 } 512 VbglR0PhysHeapFree(pReq); 513 514 /* 515 * When dret is set to dentry we got something to insert, 516 * though it may be negative (pInode == NULL). 517 */ 518 if (dret == dentry) { 519 sf_dentry_set_update_jiffies(dentry, jiffies); 460 SFLOGFLOW(("sf_lookup: parent=%p dentry=%p\n", parent, dentry)); 461 #endif 462 463 Assert(sf_g); 464 Assert(sf_i && sf_i->u32Magic == SF_INODE_INFO_MAGIC); 465 466 /* 467 * Build the path. We'll associate the path with dret's inode on success. 468 */ 469 rc = sf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path); 470 if (rc == 0) { 471 /* 472 * Do a lookup on the host side. 473 */ 474 VBOXSFCREATEREQ *pReq = (VBOXSFCREATEREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq) + path->u16Size); 475 if (pReq) { 476 struct inode *pInode = NULL; 477 478 RT_ZERO(*pReq); 479 memcpy(&pReq->StrPath, path, SHFLSTRING_HEADER_SIZE + path->u16Size); 480 pReq->CreateParms.Handle = SHFL_HANDLE_NIL; 481 pReq->CreateParms.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW; 482 483 LogFunc(("Calling VbglR0SfHostReqCreate on %s\n", path->String.utf8)); 484 rc = VbglR0SfHostReqCreate(sf_g->map.root, pReq); 485 if (RT_SUCCESS(rc)) { 486 if (pReq->CreateParms.Result == SHFL_FILE_EXISTS) { 487 /* 488 * Create an inode for the result. Since this also confirms 489 * the existence of all parent dentries, we increase their TTL. 490 */ 491 pInode = sf_create_inode(parent, dentry, path, &pReq->CreateParms.Info, sf_g, false /*fInstantiate*/); 492 if (rc == 0) { 493 path = NULL; /* given to the inode */ 494 dret = dentry; 495 } else 496 dret = (struct dentry *)ERR_PTR(-ENOMEM); 497 sf_dentry_chain_increase_parent_ttl(dentry); 498 } else if ( pReq->CreateParms.Result == SHFL_FILE_NOT_FOUND 499 || pReq->CreateParms.Result == SHFL_PATH_NOT_FOUND /*this probably should happen*/) { 500 dret = dentry; 501 } else { 502 AssertMsgFailed(("%d\n", pReq->CreateParms.Result)); 503 dret = (struct dentry *)ERR_PTR(-EPROTO); 504 } 505 } else if (rc == VERR_INVALID_NAME) { 506 dret = dentry; /* this can happen for names like 'foo*' on a Windows host */ 507 } else { 508 LogFunc(("VbglR0SfHostReqCreate failed on %s: %Rrc\n", path->String.utf8, rc)); 509 dret = (struct dentry *)ERR_PTR(-EPROTO); 510 } 511 VbglR0PhysHeapFree(pReq); 512 513 /* 514 * When dret is set to dentry we got something to insert, 515 * though it may be negative (pInode == NULL). 516 */ 517 if (dret == dentry) { 518 sf_dentry_set_update_jiffies(dentry, jiffies); 520 519 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38) 521 520 Assert(dentry->d_op == &sf_dentry_ops); /* (taken from the superblock) */ 522 521 #else 523 524 #endif 525 526 527 528 529 530 531 532 533 534 522 dentry->d_op = &sf_dentry_ops; 523 #endif 524 d_add(dentry, pInode); 525 dret = NULL; 526 } 527 } else 528 dret = (struct dentry *)ERR_PTR(-ENOMEM); 529 if (path) 530 kfree(path); 531 } else 532 dret = (struct dentry *)ERR_PTR(rc); 533 return dret; 535 534 } 536 535 … … 547 546 * @returns 0 on success, Linux error code otherwise 548 547 */ 549 static int sf_instantiate(struct inode *parent, struct dentry *dentry, 550 PSHFLSTRING path, PSHFLFSOBJINFO info, 551 SHFLHANDLE handle) 552 { 553 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(parent->i_sb); 554 struct inode *pInode = sf_create_inode(parent, dentry, path, info, sf_g, true /*fInstantiate*/); 555 if (pInode) { 556 /* Store this handle if we leave the handle open. */ 557 struct sf_inode_info *sf_new_i = GET_INODE_INFO(pInode); 558 sf_new_i->handle = handle; 559 return 0; 560 } 561 return -ENOMEM; 548 static int sf_instantiate(struct inode *parent, struct dentry *dentry, PSHFLSTRING path, PSHFLFSOBJINFO info, SHFLHANDLE handle) 549 { 550 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(parent->i_sb); 551 struct inode *pInode = sf_create_inode(parent, dentry, path, info, sf_g, true /*fInstantiate*/); 552 if (pInode) { 553 /* Store this handle if we leave the handle open. */ 554 struct sf_inode_info *sf_new_i = GET_INODE_INFO(pInode); 555 sf_new_i->handle = handle; 556 return 0; 557 } 558 return -ENOMEM; 562 559 } 563 560 … … 571 568 * @returns 0 on success, Linux error code otherwise 572 569 */ 573 static int sf_create_aux(struct inode *parent, struct dentry *dentry, 574 umode_t mode, int fDirectory) 575 { 576 int rc, err; 577 struct sf_inode_info *sf_parent_i = GET_INODE_INFO(parent); 578 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(parent->i_sb); 579 SHFLSTRING *path; 580 union CreateAuxReq 581 { 582 VBOXSFCREATEREQ Create; 583 VBOXSFCLOSEREQ Close; 584 } *pReq; 585 SHFLCREATEPARMS *pCreateParms; 586 587 TRACE(); 588 BUG_ON(!sf_parent_i); 589 BUG_ON(!sf_g); 590 591 err = sf_path_from_dentry(__func__, sf_g, sf_parent_i, dentry, &path); 592 if (err) 593 goto fail0; 594 595 /** @todo combine with sf_path_from_dentry? */ 596 pReq = (union CreateAuxReq *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + path->u16Size); 597 if (pReq) { 598 memcpy(&pReq->Create.StrPath, path, SHFLSTRING_HEADER_SIZE + path->u16Size); 599 pCreateParms = &pReq->Create.CreateParms; 600 } else { 601 err = -ENOMEM; 602 goto fail1; 603 } 604 605 RT_ZERO(*pCreateParms); 606 pCreateParms->Handle = SHFL_HANDLE_NIL; 607 pCreateParms->CreateFlags = SHFL_CF_ACT_CREATE_IF_NEW 608 | SHFL_CF_ACT_FAIL_IF_EXISTS 609 | SHFL_CF_ACCESS_READWRITE 610 | (fDirectory ? SHFL_CF_DIRECTORY : 0); 611 pCreateParms->Info.Attr.fMode = (fDirectory ? RTFS_TYPE_DIRECTORY : RTFS_TYPE_FILE) 612 | (mode & S_IRWXUGO); 613 pCreateParms->Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING; 614 615 LogFunc(("calling VbglR0SfHostReqCreate, folder %s, flags %#x\n", path->String.ach, pCreateParms->CreateFlags)); 616 rc = VbglR0SfHostReqCreate(sf_g->map.root, &pReq->Create); 617 if (RT_FAILURE(rc)) { 618 if (rc == VERR_WRITE_PROTECT) { 619 err = -EROFS; 620 goto fail2; 621 } 622 err = -EPROTO; 623 LogFunc(("(%d): SHFL_FN_CREATE(%s) failed rc=%Rrc\n", 624 fDirectory, sf_parent_i->path->String.utf8, rc)); 625 goto fail2; 626 } 627 628 if (pCreateParms->Result != SHFL_FILE_CREATED) { 629 err = -EPERM; 630 LogFunc(("(%d): could not create file %s result=%d\n", 631 fDirectory, sf_parent_i->path->String.utf8, pCreateParms->Result)); 632 goto fail2; 633 } 634 635 sf_dentry_chain_increase_parent_ttl(dentry); 636 637 err = sf_instantiate(parent, dentry, path, &pCreateParms->Info, 638 fDirectory ? SHFL_HANDLE_NIL : pCreateParms->Handle); 639 if (err) { 640 LogFunc(("(%d): could not instantiate dentry for %s err=%d\n", fDirectory, path->String.utf8, err)); 641 goto fail3; 642 } 643 644 /* 645 * Don't close this handle right now. We assume that the same file is 646 * opened with sf_reg_open() and later closed with sf_reg_close(). Save 647 * the handle in between. Does not apply to directories. True? 648 */ 649 if (fDirectory) { 650 AssertCompile(RTASSERT_OFFSET_OF(VBOXSFCREATEREQ, CreateParms.Handle) > sizeof(VBOXSFCLOSEREQ)); /* no aliasing issues */ 651 rc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, pCreateParms->Handle); 652 if (RT_FAILURE(rc)) 653 LogFunc(("(%d): VbglR0SfHostReqClose failed rc=%Rrc\n", fDirectory, rc)); 654 } 655 656 sf_parent_i->force_restat = 1; 657 VbglR0PhysHeapFree(pReq); 658 return 0; 570 static int sf_create_aux(struct inode *parent, struct dentry *dentry, umode_t mode, int fDirectory) 571 { 572 int rc, err; 573 struct sf_inode_info *sf_parent_i = GET_INODE_INFO(parent); 574 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(parent->i_sb); 575 SHFLSTRING *path; 576 union CreateAuxReq 577 { 578 VBOXSFCREATEREQ Create; 579 VBOXSFCLOSEREQ Close; 580 } *pReq; 581 SHFLCREATEPARMS *pCreateParms; 582 583 TRACE(); 584 BUG_ON(!sf_parent_i); 585 BUG_ON(!sf_g); 586 587 err = sf_path_from_dentry(__func__, sf_g, sf_parent_i, dentry, &path); 588 if (err) 589 goto fail0; 590 591 /** @todo combine with sf_path_from_dentry? */ 592 pReq = (union CreateAuxReq *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + path->u16Size); 593 if (pReq) { 594 memcpy(&pReq->Create.StrPath, path, SHFLSTRING_HEADER_SIZE + path->u16Size); 595 pCreateParms = &pReq->Create.CreateParms; 596 } else { 597 err = -ENOMEM; 598 goto fail1; 599 } 600 601 RT_ZERO(*pCreateParms); 602 pCreateParms->Handle = SHFL_HANDLE_NIL; 603 pCreateParms->CreateFlags = SHFL_CF_ACT_CREATE_IF_NEW 604 | SHFL_CF_ACT_FAIL_IF_EXISTS 605 | SHFL_CF_ACCESS_READWRITE 606 | (fDirectory ? SHFL_CF_DIRECTORY : 0); 607 pCreateParms->Info.Attr.fMode = (fDirectory ? RTFS_TYPE_DIRECTORY : RTFS_TYPE_FILE) 608 | (mode & S_IRWXUGO); 609 pCreateParms->Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING; 610 611 LogFunc(("calling VbglR0SfHostReqCreate, folder %s, flags %#x\n", path->String.ach, pCreateParms->CreateFlags)); 612 rc = VbglR0SfHostReqCreate(sf_g->map.root, &pReq->Create); 613 if (RT_FAILURE(rc)) { 614 if (rc == VERR_WRITE_PROTECT) { 615 err = -EROFS; 616 goto fail2; 617 } 618 err = -EPROTO; 619 LogFunc(("(%d): SHFL_FN_CREATE(%s) failed rc=%Rrc\n", 620 fDirectory, sf_parent_i->path->String.utf8, rc)); 621 goto fail2; 622 } 623 624 if (pCreateParms->Result != SHFL_FILE_CREATED) { 625 err = -EPERM; 626 LogFunc(("(%d): could not create file %s result=%d\n", 627 fDirectory, sf_parent_i->path->String.utf8, pCreateParms->Result)); 628 goto fail2; 629 } 630 631 sf_dentry_chain_increase_parent_ttl(dentry); 632 633 err = sf_instantiate(parent, dentry, path, &pCreateParms->Info, 634 fDirectory ? SHFL_HANDLE_NIL : pCreateParms->Handle); 635 if (err) { 636 LogFunc(("(%d): could not instantiate dentry for %s err=%d\n", fDirectory, path->String.utf8, err)); 637 goto fail3; 638 } 639 640 /* 641 * Don't close this handle right now. We assume that the same file is 642 * opened with sf_reg_open() and later closed with sf_reg_close(). Save 643 * the handle in between. Does not apply to directories. True? 644 */ 645 if (fDirectory) { 646 AssertCompile(RTASSERT_OFFSET_OF(VBOXSFCREATEREQ, CreateParms.Handle) > sizeof(VBOXSFCLOSEREQ)); /* no aliasing issues */ 647 rc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, pCreateParms->Handle); 648 if (RT_FAILURE(rc)) 649 LogFunc(("(%d): VbglR0SfHostReqClose failed rc=%Rrc\n", fDirectory, rc)); 650 } 651 652 sf_parent_i->force_restat = 1; 653 VbglR0PhysHeapFree(pReq); 654 return 0; 659 655 660 656 fail3: 661 662 663 657 rc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, pCreateParms->Handle); 658 if (RT_FAILURE(rc)) 659 LogFunc(("(%d): VbglR0SfHostReqCloseSimple failed rc=%Rrc\n", fDirectory, rc)); 664 660 fail2: 665 661 VbglR0PhysHeapFree(pReq); 666 662 fail1: 667 663 kfree(path); 668 664 669 665 fail0: 670 666 return err; 671 667 } 672 668 … … 681 677 */ 682 678 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) || defined(DOXYGEN_RUNNING) 683 static int sf_create(struct inode *parent, struct dentry *dentry, umode_t mode, 684 bool excl) 679 static int sf_create(struct inode *parent, struct dentry *dentry, umode_t mode, bool excl) 685 680 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) 686 static int sf_create(struct inode *parent, struct dentry *dentry, umode_t mode, 687 struct nameidata *nd) 681 static int sf_create(struct inode *parent, struct dentry *dentry, umode_t mode, struct nameidata *nd) 688 682 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) 689 static int sf_create(struct inode *parent, struct dentry *dentry, int mode, 690 struct nameidata *nd) 683 static int sf_create(struct inode *parent, struct dentry *dentry, int mode, struct nameidata *nd) 691 684 #else 692 685 static int sf_create(struct inode *parent, struct dentry *dentry, int mode) … … 696 689 * 2.6.0-3.5.999. In 3.6.0 atomic_open was introduced and stuff 697 690 * changed (investigate)... */ 698 699 691 TRACE(); 692 return sf_create_aux(parent, dentry, mode, 0 /*fDirectory*/); 700 693 } 701 694 … … 714 707 #endif 715 708 { 716 717 709 TRACE(); 710 return sf_create_aux(parent, dentry, mode, 1 /*fDirectory*/); 718 711 } 719 712 … … 726 719 * @returns 0 on success, Linux error code otherwise 727 720 */ 728 static int sf_unlink_aux(struct inode *parent, struct dentry *dentry, 729 int fDirectory) 730 { 731 int rc, err; 732 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(parent->i_sb); 733 struct sf_inode_info *sf_parent_i = GET_INODE_INFO(parent); 734 SHFLSTRING *path; 735 736 TRACE(); 737 BUG_ON(!sf_g); 738 739 err = sf_path_from_dentry(__func__, sf_g, sf_parent_i, dentry, &path); 740 if (!err) { 741 VBOXSFREMOVEREQ *pReq = (VBOXSFREMOVEREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFREMOVEREQ, StrPath.String) 742 + path->u16Size); 743 if (pReq) { 744 memcpy(&pReq->StrPath, path, SHFLSTRING_HEADER_SIZE + path->u16Size); 745 uint32_t fFlags = fDirectory ? SHFL_REMOVE_DIR : SHFL_REMOVE_FILE; 746 if (dentry->d_inode && ((dentry->d_inode->i_mode & S_IFLNK) == S_IFLNK)) 747 fFlags |= SHFL_REMOVE_SYMLINK; 748 749 rc = VbglR0SfHostReqRemove(sf_g->map.root, pReq, fFlags); 750 751 if (dentry->d_inode) { 752 struct sf_inode_info *sf_i = GET_INODE_INFO(dentry->d_inode); 753 sf_i->force_restat = 1; 754 sf_i->force_reread = 1; 755 } 756 757 if (RT_SUCCESS(rc)) { 758 /* directory access/change time changed */ 759 sf_parent_i->force_restat = 1; 760 /* directory content changed */ 761 sf_parent_i->force_reread = 1; 762 763 err = 0; 764 } else if (rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND) { 765 LogFunc(("(%d): VbglR0SfRemove(%s) failed rc=%Rrc; calling d_drop on %p\n", 766 fDirectory, path->String.utf8, rc, dentry)); 767 d_drop(dentry); 768 } else { 769 LogFunc(("(%d): VbglR0SfRemove(%s) failed rc=%Rrc\n", fDirectory, path->String.utf8, rc)); 770 err = -RTErrConvertToErrno(rc); 771 } 772 VbglR0PhysHeapFree(pReq); 773 } else 774 err = -ENOMEM; 775 kfree(path); 776 } 777 return err; 721 static int sf_unlink_aux(struct inode *parent, struct dentry *dentry, int fDirectory) 722 { 723 int rc, err; 724 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(parent->i_sb); 725 struct sf_inode_info *sf_parent_i = GET_INODE_INFO(parent); 726 SHFLSTRING *path; 727 728 TRACE(); 729 BUG_ON(!sf_g); 730 731 err = sf_path_from_dentry(__func__, sf_g, sf_parent_i, dentry, &path); 732 if (!err) { 733 VBOXSFREMOVEREQ *pReq = (VBOXSFREMOVEREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFREMOVEREQ, StrPath.String) 734 + path->u16Size); 735 if (pReq) { 736 memcpy(&pReq->StrPath, path, SHFLSTRING_HEADER_SIZE + path->u16Size); 737 uint32_t fFlags = fDirectory ? SHFL_REMOVE_DIR : SHFL_REMOVE_FILE; 738 if (dentry->d_inode && ((dentry->d_inode->i_mode & S_IFLNK) == S_IFLNK)) 739 fFlags |= SHFL_REMOVE_SYMLINK; 740 741 rc = VbglR0SfHostReqRemove(sf_g->map.root, pReq, fFlags); 742 743 if (dentry->d_inode) { 744 struct sf_inode_info *sf_i = GET_INODE_INFO(dentry->d_inode); 745 sf_i->force_restat = 1; 746 sf_i->force_reread = 1; 747 } 748 749 if (RT_SUCCESS(rc)) { 750 /* directory access/change time changed */ 751 sf_parent_i->force_restat = 1; 752 /* directory content changed */ 753 sf_parent_i->force_reread = 1; 754 755 err = 0; 756 } else if (rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND) { 757 LogFunc(("(%d): VbglR0SfRemove(%s) failed rc=%Rrc; calling d_drop on %p\n", 758 fDirectory, path->String.utf8, rc, dentry)); 759 d_drop(dentry); 760 } else { 761 LogFunc(("(%d): VbglR0SfRemove(%s) failed rc=%Rrc\n", fDirectory, path->String.utf8, rc)); 762 err = -RTErrConvertToErrno(rc); 763 } 764 VbglR0PhysHeapFree(pReq); 765 } else 766 err = -ENOMEM; 767 kfree(path); 768 } 769 return err; 778 770 } 779 771 … … 787 779 static int sf_unlink(struct inode *parent, struct dentry *dentry) 788 780 { 789 790 781 TRACE(); 782 return sf_unlink_aux(parent, dentry, 0 /*fDirectory*/); 791 783 } 792 784 … … 800 792 static int sf_rmdir(struct inode *parent, struct dentry *dentry) 801 793 { 802 803 794 TRACE(); 795 return sf_unlink_aux(parent, dentry, 1 /*fDirectory*/); 804 796 } 805 797 … … 815 807 */ 816 808 static int sf_rename(struct inode *old_parent, struct dentry *old_dentry, 817 809 struct inode *new_parent, struct dentry *new_dentry 818 810 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0) 819 820 #endif 821 )822 { 823 824 825 826 811 , unsigned flags 812 #endif 813 ) 814 { 815 int err = 0, rc = VINF_SUCCESS; 816 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(old_parent->i_sb); 817 818 TRACE(); 827 819 828 820 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0) 829 if (flags) { 830 LogFunc(("rename with flags=%x\n", flags)); 831 return -EINVAL; 832 } 833 #endif 834 835 if (sf_g != VBSF_GET_SUPER_INFO(new_parent->i_sb)) { 836 LogFunc(("rename with different roots\n")); 837 err = -EINVAL; 838 } else { 839 struct sf_inode_info *sf_old_i = GET_INODE_INFO(old_parent); 840 struct sf_inode_info *sf_new_i = GET_INODE_INFO(new_parent); 841 /* As we save the relative path inside the inode structure, we need to change 842 this if the rename is successful. */ 843 struct sf_inode_info *sf_file_i = 844 GET_INODE_INFO(old_dentry->d_inode); 845 SHFLSTRING *old_path; 846 SHFLSTRING *new_path; 847 848 BUG_ON(!sf_old_i); 849 BUG_ON(!sf_new_i); 850 BUG_ON(!sf_file_i); 851 852 old_path = sf_file_i->path; 853 err = sf_path_from_dentry(__func__, sf_g, sf_new_i, 854 new_dentry, &new_path); 855 if (err) 856 LogFunc(("failed to create new path\n")); 857 else { 858 VBOXSFRENAMEWITHSRCBUFREQ *pReq; 859 pReq = (VBOXSFRENAMEWITHSRCBUFREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFRENAMEWITHSRCBUFREQ, 860 StrDstPath.String) 861 + new_path->u16Size); 862 if (pReq) { 863 memcpy(&pReq->StrDstPath, new_path, SHFLSTRING_HEADER_SIZE + new_path->u16Size); 864 rc = VbglR0SfHostReqRenameWithSrcContig(sf_g->map.root, pReq, 865 old_path, virt_to_phys(old_path), 866 old_dentry->d_inode->i_mode & S_IFDIR ? SHFL_RENAME_DIR 867 : SHFL_RENAME_FILE | SHFL_RENAME_REPLACE_IF_EXISTS); 868 VbglR0PhysHeapFree(pReq); 869 } else 870 rc = VERR_NO_MEMORY; 871 if (RT_SUCCESS(rc)) { 872 kfree(old_path); 873 sf_new_i->force_restat = 1; 874 sf_old_i->force_restat = 1; /* XXX: needed? */ 875 876 /* Set the new relative path in the inode. */ 877 sf_file_i->path = new_path; 878 879 } else { 880 LogFunc(("VbglR0SfRename failed rc=%Rrc\n", 881 rc)); 882 err = -RTErrConvertToErrno(rc); 883 kfree(new_path); 884 } 885 } 886 } 887 return err; 821 if (flags) { 822 LogFunc(("rename with flags=%x\n", flags)); 823 return -EINVAL; 824 } 825 #endif 826 827 if (sf_g != VBSF_GET_SUPER_INFO(new_parent->i_sb)) { 828 LogFunc(("rename with different roots\n")); 829 err = -EINVAL; 830 } else { 831 struct sf_inode_info *sf_old_i = GET_INODE_INFO(old_parent); 832 struct sf_inode_info *sf_new_i = GET_INODE_INFO(new_parent); 833 /* As we save the relative path inside the inode structure, we need to change 834 this if the rename is successful. */ 835 struct sf_inode_info *sf_file_i = GET_INODE_INFO(old_dentry->d_inode); 836 SHFLSTRING *old_path; 837 SHFLSTRING *new_path; 838 839 BUG_ON(!sf_old_i); 840 BUG_ON(!sf_new_i); 841 BUG_ON(!sf_file_i); 842 843 old_path = sf_file_i->path; 844 err = sf_path_from_dentry(__func__, sf_g, sf_new_i, 845 new_dentry, &new_path); 846 if (err) 847 LogFunc(("failed to create new path\n")); 848 else { 849 VBOXSFRENAMEWITHSRCBUFREQ *pReq; 850 pReq = (VBOXSFRENAMEWITHSRCBUFREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFRENAMEWITHSRCBUFREQ, 851 StrDstPath.String) 852 + new_path->u16Size); 853 if (pReq) { 854 memcpy(&pReq->StrDstPath, new_path, SHFLSTRING_HEADER_SIZE + new_path->u16Size); 855 rc = VbglR0SfHostReqRenameWithSrcContig(sf_g->map.root, pReq, 856 old_path, virt_to_phys(old_path), 857 old_dentry->d_inode->i_mode & S_IFDIR ? SHFL_RENAME_DIR 858 : SHFL_RENAME_FILE | SHFL_RENAME_REPLACE_IF_EXISTS); 859 VbglR0PhysHeapFree(pReq); 860 } else 861 rc = VERR_NO_MEMORY; 862 if (RT_SUCCESS(rc)) { 863 kfree(old_path); 864 sf_new_i->force_restat = 1; 865 sf_old_i->force_restat = 1; /* XXX: needed? */ 866 867 /* Set the new relative path in the inode. */ 868 sf_file_i->path = new_path; 869 870 } else { 871 LogFunc(("VbglR0SfRename failed rc=%Rrc\n", 872 rc)); 873 err = -RTErrConvertToErrno(rc); 874 kfree(new_path); 875 } 876 } 877 } 878 return err; 888 879 } 889 880 890 881 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) 891 static int sf_symlink(struct inode *parent, struct dentry *dentry, 892 const char *symname) 893 { 894 int err; 895 int rc; 896 struct sf_inode_info *sf_i; 897 struct vbsf_super_info *sf_g; 898 SHFLSTRING *path, *ssymname; 899 SHFLFSOBJINFO info; 900 int symname_len = strlen(symname) + 1; 901 902 TRACE(); 903 sf_g = VBSF_GET_SUPER_INFO(parent->i_sb); 904 sf_i = GET_INODE_INFO(parent); 905 906 BUG_ON(!sf_g); 907 BUG_ON(!sf_i); 908 909 err = sf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path); 910 if (err) 911 goto fail0; 912 913 ssymname = 914 kmalloc(offsetof(SHFLSTRING, String.utf8) + symname_len, 915 GFP_KERNEL); 916 if (!ssymname) { 917 LogRelFunc(("kmalloc failed, caller=sf_symlink\n")); 918 err = -ENOMEM; 919 goto fail1; 920 } 921 922 ssymname->u16Length = symname_len - 1; 923 ssymname->u16Size = symname_len; 924 memcpy(ssymname->String.utf8, symname, symname_len); 925 926 rc = VbglR0SfSymlink(&client_handle, &sf_g->map, path, ssymname, &info); 927 kfree(ssymname); 928 929 if (RT_FAILURE(rc)) { 930 if (rc == VERR_WRITE_PROTECT) { 931 err = -EROFS; 932 goto fail1; 933 } 934 LogFunc(("VbglR0SfSymlink(%s) failed rc=%Rrc\n", 935 sf_i->path->String.utf8, rc)); 936 err = -EPROTO; 937 goto fail1; 938 } 939 940 err = sf_instantiate(parent, dentry, path, &info, SHFL_HANDLE_NIL); 941 if (err) { 942 LogFunc(("could not instantiate dentry for %s err=%d\n", 943 sf_i->path->String.utf8, err)); 944 goto fail1; 945 } 946 947 sf_i->force_restat = 1; 948 return 0; 882 static int sf_symlink(struct inode *parent, struct dentry *dentry, const char *symname) 883 { 884 int err; 885 int rc; 886 struct sf_inode_info *sf_i; 887 struct vbsf_super_info *sf_g; 888 SHFLSTRING *path, *ssymname; 889 SHFLFSOBJINFO info; 890 int symname_len = strlen(symname) + 1; 891 892 TRACE(); 893 sf_g = VBSF_GET_SUPER_INFO(parent->i_sb); 894 sf_i = GET_INODE_INFO(parent); 895 896 BUG_ON(!sf_g); 897 BUG_ON(!sf_i); 898 899 err = sf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path); 900 if (err) 901 goto fail0; 902 903 ssymname = 904 kmalloc(offsetof(SHFLSTRING, String.utf8) + symname_len, 905 GFP_KERNEL); 906 if (!ssymname) { 907 LogRelFunc(("kmalloc failed, caller=sf_symlink\n")); 908 err = -ENOMEM; 909 goto fail1; 910 } 911 912 ssymname->u16Length = symname_len - 1; 913 ssymname->u16Size = symname_len; 914 memcpy(ssymname->String.utf8, symname, symname_len); 915 916 rc = VbglR0SfSymlink(&client_handle, &sf_g->map, path, ssymname, &info); 917 kfree(ssymname); 918 919 if (RT_FAILURE(rc)) { 920 if (rc == VERR_WRITE_PROTECT) { 921 err = -EROFS; 922 goto fail1; 923 } 924 LogFunc(("VbglR0SfSymlink(%s) failed rc=%Rrc\n", 925 sf_i->path->String.utf8, rc)); 926 err = -EPROTO; 927 goto fail1; 928 } 929 930 err = sf_instantiate(parent, dentry, path, &info, SHFL_HANDLE_NIL); 931 if (err) { 932 LogFunc(("could not instantiate dentry for %s err=%d\n", 933 sf_i->path->String.utf8, err)); 934 goto fail1; 935 } 936 937 sf_i->force_restat = 1; 938 return 0; 949 939 950 940 fail1: 951 941 kfree(path); 952 942 fail0: 953 943 return err; 954 944 } 955 945 #endif /* LINUX_VERSION_CODE >= 2.6.0 */ 956 946 957 947 struct inode_operations sf_dir_iops = { 958 959 960 961 962 963 948 .lookup = sf_lookup, 949 .create = sf_create, 950 .mkdir = sf_mkdir, 951 .rmdir = sf_rmdir, 952 .unlink = sf_unlink, 953 .rename = sf_rename, 964 954 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) 965 955 .revalidate = sf_inode_revalidate 966 956 #else 967 968 969 957 .getattr = sf_getattr, 958 .setattr = sf_setattr, 959 .symlink = sf_symlink 970 960 #endif 971 961 }; 962 -
trunk/src/VBox/Additions/linux/sharedfolders/lnkops.c
r77524 r77526 42 42 # endif 43 43 { 44 45 46 47 48 49 44 struct inode *inode = dentry->d_inode; 45 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb); 46 struct sf_inode_info *sf_i = GET_INODE_INFO(inode); 47 int error = -ENOMEM; 48 char *path = (char *)get_zeroed_page(GFP_KERNEL); 49 int rc; 50 50 51 52 53 54 55 56 57 58 59 60 51 if (path) { 52 error = 0; 53 rc = VbglR0SfReadLink(&client_handle, &sf_g->map, sf_i->path, 54 PATH_MAX, path); 55 if (RT_FAILURE(rc)) { 56 LogFunc(("VbglR0SfReadLink failed, caller=%s, rc=%Rrc\n", __func__, rc)); 57 free_page((unsigned long)path); 58 error = -EPROTO; 59 } 60 } 61 61 # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) 62 62 return error ? ERR_PTR(error) : (*cookie = path); 63 63 # else 64 64 nd_set_link(nd, error ? ERR_PTR(error) : path); 65 65 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) 66 66 return NULL; 67 67 # else 68 68 return 0; 69 69 # endif 70 70 #endif … … 74 74 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) 75 75 static void sf_put_link(struct dentry *dentry, struct nameidata *nd, 76 76 void *cookie) 77 77 #else 78 78 static void sf_put_link(struct dentry *dentry, struct nameidata *nd) 79 79 #endif 80 80 { 81 82 83 81 char *page = nd_get_link(nd); 82 if (!IS_ERR(page)) 83 free_page((unsigned long)page); 84 84 } 85 85 # endif … … 87 87 # else /* LINUX_VERSION_CODE >= 4.5.0 */ 88 88 static const char *sf_get_link(struct dentry *dentry, struct inode *inode, 89 89 struct delayed_call *done) 90 90 { 91 92 93 94 91 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb); 92 struct sf_inode_info *sf_i = GET_INODE_INFO(inode); 93 char *path; 94 int rc; 95 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 96 if (!dentry) 97 return ERR_PTR(-ECHILD); 98 path = kzalloc(PAGE_SIZE, GFP_KERNEL); 99 if (!path) 100 return ERR_PTR(-ENOMEM); 101 rc = VbglR0SfReadLink(&client_handle, &sf_g->map, sf_i->path, PATH_MAX, 102 path); 103 if (RT_FAILURE(rc)) { 104 LogFunc(("VbglR0SfReadLink failed, caller=%s, rc=%Rrc\n", 105 __func__, rc)); 106 kfree(path); 107 return ERR_PTR(-EPROTO); 108 } 109 set_delayed_call(done, kfree_link, path); 110 return path; 111 111 } 112 112 # endif /* LINUX_VERSION_CODE >= 4.5.0 */ … … 114 114 struct inode_operations sf_lnk_iops = { 115 115 # if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) 116 116 .readlink = generic_readlink, 117 117 # endif 118 118 # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) 119 119 .get_link = sf_get_link 120 120 # elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) 121 122 121 .follow_link = sf_follow_link, 122 .put_link = free_page_put_link, 123 123 # else 124 125 124 .follow_link = sf_follow_link, 125 .put_link = sf_put_link 126 126 # endif 127 127 }; 128 128 129 #endif 129 #endif /* LINUX_VERSION_CODE >= 2.6.8 */ -
trunk/src/VBox/Additions/linux/sharedfolders/regops.c
r77524 r77526 60 60 void sf_handle_drop_chain(struct sf_inode_info *pInodeInfo) 61 61 { 62 63 64 65 66 67 68 69 70 71 72 73 74 62 struct sf_handle *pCur, *pNext; 63 unsigned long fSavedFlags; 64 SFLOGFLOW(("sf_handle_drop_chain: %p\n", pInodeInfo)); 65 spin_lock_irqsave(&g_SfHandleLock, fSavedFlags); 66 67 RTListForEachSafe(&pInodeInfo->HandleList, pCur, pNext, struct sf_handle, Entry) { 68 AssertMsg((pCur->fFlags & (SF_HANDLE_F_MAGIC_MASK | SF_HANDLE_F_ON_LIST)) == (SF_HANDLE_F_MAGIC | SF_HANDLE_F_ON_LIST), 69 ("%p %#x\n", pCur, pCur->fFlags)); 70 pCur->fFlags |= SF_HANDLE_F_ON_LIST; 71 RTListNodeRemove(&pCur->Entry); 72 } 73 74 spin_unlock_irqrestore(&g_SfHandleLock, fSavedFlags); 75 75 } 76 76 … … 87 87 struct sf_handle *sf_handle_find(struct sf_inode_info *pInodeInfo, uint32_t fFlagsSet, uint32_t fFlagsClear) 88 88 { 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 89 struct sf_handle *pCur; 90 unsigned long fSavedFlags; 91 spin_lock_irqsave(&g_SfHandleLock, fSavedFlags); 92 93 RTListForEach(&pInodeInfo->HandleList, pCur, struct sf_handle, Entry) { 94 AssertMsg((pCur->fFlags & (SF_HANDLE_F_MAGIC_MASK | SF_HANDLE_F_ON_LIST)) == (SF_HANDLE_F_MAGIC | SF_HANDLE_F_ON_LIST), 95 ("%p %#x\n", pCur, pCur->fFlags)); 96 if ((pCur->fFlags & (fFlagsSet | fFlagsClear)) == fFlagsSet) { 97 uint32_t cRefs = ASMAtomicIncU32(&pCur->cRefs); 98 if (cRefs > 1) { 99 spin_unlock_irqrestore(&g_SfHandleLock, fSavedFlags); 100 SFLOGFLOW(("sf_handle_find: returns %p\n", pCur)); 101 return pCur; 102 } 103 /* Oops, already being closed (safe as it's only ever increased here). */ 104 ASMAtomicDecU32(&pCur->cRefs); 105 } 106 } 107 108 spin_unlock_irqrestore(&g_SfHandleLock, fSavedFlags); 109 SFLOGFLOW(("sf_handle_find: returns NULL!\n")); 110 return NULL; 111 111 } 112 112 … … 118 118 * @param pHandle The handle to release. 119 119 * @param sf_g The info structure for the shared folder associated 120 * 120 * with the handle. 121 121 * @param pszCaller The caller name (for logging failures). 122 122 */ 123 123 uint32_t sf_handle_release_slow(struct sf_handle *pHandle, struct vbsf_super_info *sf_g, const char *pszCaller) 124 124 { 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 125 int rc; 126 unsigned long fSavedFlags; 127 128 SFLOGFLOW(("sf_handle_release_slow: %p (%s)\n", pHandle, pszCaller)); 129 130 /* 131 * Remove from the list. 132 */ 133 spin_lock_irqsave(&g_SfHandleLock, fSavedFlags); 134 135 AssertMsg((pHandle->fFlags & SF_HANDLE_F_MAGIC_MASK) == SF_HANDLE_F_MAGIC, ("%p %#x\n", pHandle, pHandle->fFlags)); 136 Assert(pHandle->pInodeInfo); 137 Assert(pHandle->pInodeInfo && pHandle->pInodeInfo->u32Magic == SF_INODE_INFO_MAGIC); 138 139 if (pHandle->fFlags & SF_HANDLE_F_ON_LIST) { 140 pHandle->fFlags &= ~SF_HANDLE_F_ON_LIST; 141 RTListNodeRemove(&pHandle->Entry); 142 } 143 144 spin_unlock_irqrestore(&g_SfHandleLock, fSavedFlags); 145 146 /* 147 * Actually destroy it. 148 */ 149 rc = VbglR0SfHostReqCloseSimple(sf_g->map.root, pHandle->hHost); 150 if (RT_FAILURE(rc)) 151 LogFunc(("Caller %s: VbglR0SfHostReqCloseSimple %#RX64 failed with rc=%Rrc\n", pszCaller, pHandle->hHost, rc)); 152 pHandle->hHost = SHFL_HANDLE_NIL; 153 pHandle->fFlags = SF_HANDLE_F_MAGIC_DEAD; 154 kfree(pHandle); 155 return 0; 156 156 } 157 157 … … 166 166 { 167 167 #ifdef VBOX_STRICT 168 169 #endif 170 171 172 173 174 175 176 177 178 179 180 168 struct sf_handle *pCur; 169 #endif 170 unsigned long fSavedFlags; 171 172 SFLOGFLOW(("sf_handle_append: %p (to %p)\n", pHandle, pInodeInfo)); 173 AssertMsg((pHandle->fFlags & (SF_HANDLE_F_MAGIC_MASK | SF_HANDLE_F_ON_LIST)) == SF_HANDLE_F_MAGIC, 174 ("%p %#x\n", pHandle, pHandle->fFlags)); 175 Assert(pInodeInfo->u32Magic == SF_INODE_INFO_MAGIC); 176 177 spin_lock_irqsave(&g_SfHandleLock, fSavedFlags); 178 179 AssertMsg((pHandle->fFlags & (SF_HANDLE_F_MAGIC_MASK | SF_HANDLE_F_ON_LIST)) == SF_HANDLE_F_MAGIC, 180 ("%p %#x\n", pHandle, pHandle->fFlags)); 181 181 #ifdef VBOX_STRICT 182 183 184 185 186 187 188 #endif 189 190 191 192 193 182 RTListForEach(&pInodeInfo->HandleList, pCur, struct sf_handle, Entry) { 183 Assert(pCur != pHandle); 184 AssertMsg((pCur->fFlags & (SF_HANDLE_F_MAGIC_MASK | SF_HANDLE_F_ON_LIST)) == (SF_HANDLE_F_MAGIC | SF_HANDLE_F_ON_LIST), 185 ("%p %#x\n", pCur, pCur->fFlags)); 186 } 187 pHandle->pInodeInfo = pInodeInfo; 188 #endif 189 190 pHandle->fFlags |= SF_HANDLE_F_ON_LIST; 191 RTListAppend(&pInodeInfo->HandleList, &pHandle->Entry); 192 193 spin_unlock_irqrestore(&g_SfHandleLock, fSavedFlags); 194 194 } 195 195 … … 200 200 void free_pipebuf(struct page *kpage) 201 201 { 202 203 202 kunmap(kpage); 203 __free_pages(kpage, 0); 204 204 } 205 205 206 206 void *sf_pipe_buf_map(struct pipe_inode_info *pipe, 207 208 { 209 207 struct pipe_buffer *pipe_buf, int atomic) 208 { 209 return 0; 210 210 } 211 211 … … 215 215 216 216 void sf_pipe_buf_unmap(struct pipe_inode_info *pipe, 217 217 struct pipe_buffer *pipe_buf, void *map_data) 218 218 { 219 219 } 220 220 221 221 int sf_pipe_buf_steal(struct pipe_inode_info *pipe, 222 223 { 224 222 struct pipe_buffer *pipe_buf) 223 { 224 return 0; 225 225 } 226 226 227 227 static void sf_pipe_buf_release(struct pipe_inode_info *pipe, 228 229 { 230 228 struct pipe_buffer *pipe_buf) 229 { 230 free_pipebuf(pipe_buf->page); 231 231 } 232 232 233 233 int sf_pipe_buf_confirm(struct pipe_inode_info *info, 234 235 { 236 234 struct pipe_buffer *pipe_buf) 235 { 236 return 0; 237 237 } 238 238 239 239 static struct pipe_buf_operations sf_pipe_buf_ops = { 240 241 242 243 244 245 246 240 .can_merge = 0, 241 .map = sf_pipe_buf_map, 242 .unmap = sf_pipe_buf_unmap, 243 .confirm = sf_pipe_buf_confirm, 244 .release = sf_pipe_buf_release, 245 .steal = sf_pipe_buf_steal, 246 .get = sf_pipe_buf_get, 247 247 }; 248 248 249 249 static int sf_reg_read_aux(const char *caller, struct vbsf_super_info *sf_g, 250 251 252 { 253 254 255 256 257 258 259 260 250 struct sf_reg_info *sf_r, void *buf, 251 uint32_t * nread, uint64_t pos) 252 { 253 int rc = VbglR0SfRead(&client_handle, &sf_g->map, sf_r->Handle.hHost, 254 pos, nread, buf, false /* already locked? */ ); 255 if (RT_FAILURE(rc)) { 256 LogFunc(("VbglR0SfRead failed. caller=%s, rc=%Rrc\n", caller, 257 rc)); 258 return -EPROTO; 259 } 260 return 0; 261 261 } 262 262 … … 266 266 ssize_t 267 267 sf_splice_read(struct file *in, loff_t * poffset, 268 269 { 270 271 272 273 274 275 276 277 278 268 struct pipe_inode_info *pipe, size_t len, unsigned int flags) 269 { 270 size_t bytes_remaining = len; 271 loff_t orig_offset = *poffset; 272 loff_t offset = orig_offset; 273 struct inode *inode = GET_F_DENTRY(in)->d_inode; 274 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb); 275 struct sf_reg_info *sf_r = in->private_data; 276 ssize_t retval; 277 struct page *kpage = 0; 278 size_t nsent = 0; 279 279 280 280 /** @todo rig up a FsPerf test for this code */ 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 } else {/* pipe full */338 339 340 341 342 343 344 345 346 347 348 349 350 351 281 TRACE(); 282 if (!S_ISREG(inode->i_mode)) { 283 LogFunc(("read from non regular file %d\n", inode->i_mode)); 284 return -EINVAL; 285 } 286 if (!len) { 287 return 0; 288 } 289 290 LOCK_PIPE(pipe); 291 292 uint32_t req_size = 0; 293 while (bytes_remaining > 0) { 294 kpage = alloc_page(GFP_KERNEL); 295 if (unlikely(kpage == NULL)) { 296 UNLOCK_PIPE(pipe); 297 return -ENOMEM; 298 } 299 req_size = 0; 300 uint32_t nread = req_size = 301 (uint32_t) min(bytes_remaining, (size_t) PAGE_SIZE); 302 uint32_t chunk = 0; 303 void *kbuf = kmap(kpage); 304 while (chunk < req_size) { 305 retval = 306 sf_reg_read_aux(__func__, sf_g, sf_r, kbuf + chunk, 307 &nread, offset); 308 if (retval < 0) 309 goto err; 310 if (nread == 0) 311 break; 312 chunk += nread; 313 offset += nread; 314 nread = req_size - chunk; 315 } 316 if (!pipe->readers) { 317 send_sig(SIGPIPE, current, 0); 318 retval = -EPIPE; 319 goto err; 320 } 321 if (pipe->nrbufs < PIPE_BUFFERS) { 322 struct pipe_buffer *pipebuf = 323 pipe->bufs + 324 ((pipe->curbuf + pipe->nrbufs) & (PIPE_BUFFERS - 325 1)); 326 pipebuf->page = kpage; 327 pipebuf->ops = &sf_pipe_buf_ops; 328 pipebuf->len = req_size; 329 pipebuf->offset = 0; 330 pipebuf->private = 0; 331 pipebuf->flags = 0; 332 pipe->nrbufs++; 333 nsent += req_size; 334 bytes_remaining -= req_size; 335 if (signal_pending(current)) 336 break; 337 } else { /* pipe full */ 338 339 if (flags & SPLICE_F_NONBLOCK) { 340 retval = -EAGAIN; 341 goto err; 342 } 343 free_pipebuf(kpage); 344 break; 345 } 346 } 347 UNLOCK_PIPE(pipe); 348 if (!nsent && signal_pending(current)) 349 return -ERESTARTSYS; 350 *poffset += nsent; 351 return offset - orig_offset; 352 352 353 353 err: 354 355 356 354 UNLOCK_PIPE(pipe); 355 free_pipebuf(kpage); 356 return retval; 357 357 } 358 358 … … 365 365 while (cPages-- > 0) 366 366 { 367 368 369 367 struct page *pPage = papPages[cPages]; 368 if (fSetDirty && !PageReserved(pPage)) 369 SetPageDirty(pPage); 370 370 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) 371 371 put_page(pPage); 372 372 #else 373 373 page_cache_release(pPage); 374 374 #endif 375 375 } … … 381 381 { 382 382 # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0) 383 384 383 ssize_t cPagesLocked = get_user_pages_unlocked(uPtrFrom, cPages, papPages, 384 fWrite ? FOLL_WRITE | FOLL_FORCE : FOLL_FORCE); 385 385 # elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) 386 386 ssize_t cPagesLocked = get_user_pages_unlocked(uPtrFrom, cPages, fWrite, 1 /*force*/, papPages); 387 387 # elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) 388 389 388 ssize_t cPagesLocked = get_user_pages_unlocked(current, current->mm, uPtrFrom, cPages, 389 fWrite, 1 /*force*/, papPages); 390 390 # else 391 392 393 394 395 391 struct task_struct *pTask = current; 392 size_t cPagesLocked; 393 down_read(&pTask->mm->mmap_sem); 394 cPagesLocked = get_user_pages(current, current->mm, uPtrFrom, cPages, fWrite, 1 /*force*/, papPages, NULL); 395 up_read(&pTask->mm->mmap_sem); 396 396 # endif 397 398 399 400 401 402 403 404 405 397 if (cPagesLocked == cPages) 398 return 0; 399 if (cPagesLocked < 0) 400 return cPagesLocked; 401 402 sf_unlock_user_pages(papPages, cPagesLocked, false /*fSetDirty*/); 403 404 /* We could use uPtrFrom + cPagesLocked to get the correct status here... */ 405 return -EFAULT; 406 406 } 407 407 … … 416 416 { 417 417 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) 418 419 420 421 422 423 424 425 426 427 428 429 430 418 struct iovec iov = { .iov_base = buf, .iov_len = size }; 419 struct iov_iter iter; 420 struct kiocb kiocb; 421 ssize_t cbRet; 422 423 init_sync_kiocb(&kiocb, file); 424 kiocb.ki_pos = *off; 425 iov_iter_init(&iter, READ, &iov, 1, size); 426 427 cbRet = generic_file_read_iter(&kiocb, &iter); 428 429 *off = kiocb.ki_pos; 430 return cbRet; 431 431 432 432 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) 433 434 435 436 437 438 439 440 441 442 443 444 445 433 struct iovec iov = { .iov_base = buf, .iov_len = size }; 434 struct kiocb kiocb; 435 ssize_t cbRet; 436 437 init_sync_kiocb(&kiocb, file); 438 kiocb.ki_pos = *off; 439 440 cbRet = generic_file_aio_read(&kiocb, &iov, 1, *off); 441 if (cbRet == -EIOCBQUEUED) 442 cbRet = wait_on_sync_kiocb(&kiocb); 443 444 *off = kiocb.ki_pos; 445 return cbRet; 446 446 447 447 #else /* 2.6.18 or earlier: */ 448 448 return generic_file_read(file, buf, size, off); 449 449 #endif 450 450 } … … 456 456 */ 457 457 static ssize_t sf_reg_read_fallback(struct file *file, char /*__user*/ *buf, size_t size, loff_t *off, 458 459 { 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 458 struct vbsf_super_info *sf_g, struct sf_reg_info *sf_r) 459 { 460 /* 461 * Lock pages and execute the read, taking care not to pass the host 462 * more than it can handle in one go or more than we care to allocate 463 * page arrays for. The latter limit is set at just short of 32KB due 464 * to how the physical heap works. 465 */ 466 struct page *apPagesStack[16]; 467 struct page **papPages = &apPagesStack[0]; 468 struct page **papPagesFree = NULL; 469 VBOXSFREADPGLSTREQ *pReq; 470 loff_t offFile = *off; 471 ssize_t cbRet = -ENOMEM; 472 size_t cPages = (((uintptr_t)buf & PAGE_OFFSET_MASK) + size + PAGE_OFFSET_MASK) >> PAGE_SHIFT; 473 size_t cMaxPages = RT_MIN(RT_MAX(sf_g->cMaxIoPages, 1), cPages); 474 475 pReq = (VBOXSFREADPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFREADPGLSTREQ, PgLst.aPages[cMaxPages])); 476 while (!pReq && cMaxPages > 4) { 477 cMaxPages /= 2; 478 pReq = (VBOXSFREADPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFREADPGLSTREQ, PgLst.aPages[cMaxPages])); 479 } 480 if (pReq && cPages > RT_ELEMENTS(apPagesStack)) 481 papPagesFree = papPages = kmalloc(cMaxPages * sizeof(sizeof(papPages[0])), GFP_KERNEL); 482 if (pReq && papPages) { 483 cbRet = 0; 484 for (;;) { 485 /* 486 * Figure out how much to process now and lock the user pages. 487 */ 488 int rc; 489 size_t cbChunk = (uintptr_t)buf & PAGE_OFFSET_MASK; 490 pReq->PgLst.offFirstPage = (uint16_t)cbChunk; 491 cPages = RT_ALIGN_Z(cbChunk + size, PAGE_SIZE) >> PAGE_SHIFT; 492 if (cPages <= cMaxPages) 493 cbChunk = size; 494 else { 495 cPages = cMaxPages; 496 cbChunk = (cMaxPages << PAGE_SHIFT) - cbChunk; 497 } 498 499 rc = sf_lock_user_pages((uintptr_t)buf, cPages, true /*fWrite*/, papPages); 500 if (rc == 0) { 501 size_t iPage = cPages; 502 while (iPage-- > 0) 503 pReq->PgLst.aPages[iPage] = page_to_phys(papPages[iPage]); 504 } else { 505 cbRet = rc; 506 break; 507 } 508 509 /* 510 * Issue the request and unlock the pages. 511 */ 512 rc = VbglR0SfHostReqReadPgLst(sf_g->map.root, pReq, sf_r->Handle.hHost, offFile, cbChunk, cPages); 513 514 sf_unlock_user_pages(papPages, cPages, true /*fSetDirty*/); 515 516 if (RT_SUCCESS(rc)) { 517 /* 518 * Success, advance position and buffer. 519 */ 520 uint32_t cbActual = pReq->Parms.cb32Read.u.value32; 521 AssertStmt(cbActual <= cbChunk, cbActual = cbChunk); 522 cbRet += cbActual; 523 offFile += cbActual; 524 buf = (uint8_t *)buf + cbActual; 525 size -= cbActual; 526 527 /* 528 * Are we done already? If so commit the new file offset. 529 */ 530 if (!size || cbActual < cbChunk) { 531 *off = offFile; 532 break; 533 } 534 } else if (rc == VERR_NO_MEMORY && cMaxPages > 4) { 535 /* 536 * The host probably doesn't have enough heap to handle the 537 * request, reduce the page count and retry. 538 */ 539 cMaxPages /= 4; 540 Assert(cMaxPages > 0); 541 } else { 542 /* 543 * If we've successfully read stuff, return it rather than 544 * the error. (Not sure if this is such a great idea...) 545 */ 546 if (cbRet > 0) 547 *off = offFile; 548 else 549 cbRet = -EPROTO; 550 break; 551 } 552 } 553 } 554 if (papPagesFree) 555 kfree(papPages); 556 if (pReq) 557 VbglR0PhysHeapFree(pReq); 558 return cbRet; 559 559 } 560 560 … … 569 569 * @returns the number of read bytes on success, Linux error code otherwise 570 570 */ 571 static ssize_t sf_reg_read(struct file *file, char /*__user*/ *buf, size_t size, 572 loff_t *off) 573 { 574 struct inode *inode = GET_F_DENTRY(file)->d_inode; 575 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb); 576 struct sf_reg_info *sf_r = file->private_data; 577 struct address_space *mapping = inode->i_mapping; 578 579 SFLOGFLOW(("sf_reg_read: inode=%p file=%p buf=%p size=%#zx off=%#llx\n", inode, file, buf, size, *off)); 580 581 if (!S_ISREG(inode->i_mode)) { 582 LogFunc(("read from non regular file %d\n", inode->i_mode)); 583 return -EINVAL; 584 } 585 586 /** @todo XXX Check read permission according to inode->i_mode! */ 587 588 if (!size) 589 return 0; 590 591 /* 592 * If there is a mapping and O_DIRECT isn't in effect, we must at a 593 * heed dirty pages in the mapping and read from them. For simplicity 594 * though, we just do page cache reading when there are writable 595 * mappings around with any kind of pages loaded. 596 */ 597 if ( mapping 598 && mapping->nrpages > 0 599 && mapping_writably_mapped(mapping) 600 && !(file->f_flags & O_DIRECT) 601 && 1 /** @todo make this behaviour configurable */ ) 602 return sf_reg_read_mapped(file, buf, size, off); 603 604 /* 605 * For small requests, try use an embedded buffer provided we get a heap block 606 * that does not cross page boundraries (see host code). 607 */ 608 if (size <= PAGE_SIZE / 4 * 3 - RT_UOFFSETOF(VBOXSFREADEMBEDDEDREQ, abData[0]) /* see allocator */) { 609 uint32_t const cbReq = RT_UOFFSETOF(VBOXSFREADEMBEDDEDREQ, abData[0]) + size; 610 VBOXSFREADEMBEDDEDREQ *pReq = (VBOXSFREADEMBEDDEDREQ *)VbglR0PhysHeapAlloc(cbReq); 611 if ( pReq 612 && (PAGE_SIZE - ((uintptr_t)pReq & PAGE_OFFSET_MASK)) >= cbReq) { 613 ssize_t cbRet; 614 int vrc = VbglR0SfHostReqReadEmbedded(sf_g->map.root, pReq, sf_r->Handle.hHost, *off, (uint32_t)size); 615 if (RT_SUCCESS(vrc)) { 616 cbRet = pReq->Parms.cb32Read.u.value32; 617 AssertStmt(cbRet <= (ssize_t)size, cbRet = size); 618 if (copy_to_user(buf, pReq->abData, cbRet) == 0) 619 *off += cbRet; 620 else 621 cbRet = -EFAULT; 622 } else 623 cbRet = -EPROTO; 624 VbglR0PhysHeapFree(pReq); 625 return cbRet; 626 } 627 if (pReq) 628 VbglR0PhysHeapFree(pReq); 629 } 571 static ssize_t sf_reg_read(struct file *file, char /*__user*/ *buf, size_t size, loff_t *off) 572 { 573 struct inode *inode = GET_F_DENTRY(file)->d_inode; 574 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb); 575 struct sf_reg_info *sf_r = file->private_data; 576 struct address_space *mapping = inode->i_mapping; 577 578 SFLOGFLOW(("sf_reg_read: inode=%p file=%p buf=%p size=%#zx off=%#llx\n", inode, file, buf, size, *off)); 579 580 if (!S_ISREG(inode->i_mode)) { 581 LogFunc(("read from non regular file %d\n", inode->i_mode)); 582 return -EINVAL; 583 } 584 585 /** @todo XXX Check read permission according to inode->i_mode! */ 586 587 if (!size) 588 return 0; 589 590 /* 591 * If there is a mapping and O_DIRECT isn't in effect, we must at a 592 * heed dirty pages in the mapping and read from them. For simplicity 593 * though, we just do page cache reading when there are writable 594 * mappings around with any kind of pages loaded. 595 */ 596 if ( mapping 597 && mapping->nrpages > 0 598 && mapping_writably_mapped(mapping) 599 && !(file->f_flags & O_DIRECT) 600 && 1 /** @todo make this behaviour configurable */ ) 601 return sf_reg_read_mapped(file, buf, size, off); 602 603 /* 604 * For small requests, try use an embedded buffer provided we get a heap block 605 * that does not cross page boundraries (see host code). 606 */ 607 if (size <= PAGE_SIZE / 4 * 3 - RT_UOFFSETOF(VBOXSFREADEMBEDDEDREQ, abData[0]) /* see allocator */) { 608 uint32_t const cbReq = RT_UOFFSETOF(VBOXSFREADEMBEDDEDREQ, abData[0]) + size; 609 VBOXSFREADEMBEDDEDREQ *pReq = (VBOXSFREADEMBEDDEDREQ *)VbglR0PhysHeapAlloc(cbReq); 610 if ( pReq 611 && (PAGE_SIZE - ((uintptr_t)pReq & PAGE_OFFSET_MASK)) >= cbReq) { 612 ssize_t cbRet; 613 int vrc = VbglR0SfHostReqReadEmbedded(sf_g->map.root, pReq, sf_r->Handle.hHost, *off, (uint32_t)size); 614 if (RT_SUCCESS(vrc)) { 615 cbRet = pReq->Parms.cb32Read.u.value32; 616 AssertStmt(cbRet <= (ssize_t)size, cbRet = size); 617 if (copy_to_user(buf, pReq->abData, cbRet) == 0) 618 *off += cbRet; 619 else 620 cbRet = -EFAULT; 621 } else 622 cbRet = -EPROTO; 623 VbglR0PhysHeapFree(pReq); 624 return cbRet; 625 } 626 if (pReq) 627 VbglR0PhysHeapFree(pReq); 628 } 630 629 631 630 #if 0 /* Turns out this is slightly slower than locking the pages even for 4KB reads (4.19/amd64). */ 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 #endif 660 661 631 /* 632 * For medium sized requests try use a bounce buffer. 633 */ 634 if (size <= _64K /** @todo make this configurable? */) { 635 void *pvBounce = kmalloc(size, GFP_KERNEL); 636 if (pvBounce) { 637 VBOXSFREADPGLSTREQ *pReq = (VBOXSFREADPGLSTREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq)); 638 if (pReq) { 639 ssize_t cbRet; 640 int vrc = VbglR0SfHostReqReadContig(sf_g->map.root, pReq, sf_r->Handle.hHost, *off, 641 (uint32_t)size, pvBounce, virt_to_phys(pvBounce)); 642 if (RT_SUCCESS(vrc)) { 643 cbRet = pReq->Parms.cb32Read.u.value32; 644 AssertStmt(cbRet <= (ssize_t)size, cbRet = size); 645 if (copy_to_user(buf, pvBounce, cbRet) == 0) 646 *off += cbRet; 647 else 648 cbRet = -EFAULT; 649 } else 650 cbRet = -EPROTO; 651 VbglR0PhysHeapFree(pReq); 652 kfree(pvBounce); 653 return cbRet; 654 } 655 kfree(pvBounce); 656 } 657 } 658 #endif 659 660 return sf_reg_read_fallback(file, buf, size, off, sf_g, sf_r); 662 661 } 663 662 … … 669 668 DECLINLINE(void) sf_reg_write_invalidate_mapping_range(struct address_space *mapping, loff_t offStart, loff_t offEnd) 670 669 { 671 672 673 674 675 676 677 678 679 670 /* 671 * Only bother with this if the mapping has any pages in it. 672 * 673 * Note! According to the docs, the last parameter, end, is inclusive (we 674 * would have named it 'last' to indicate this). 675 * 676 * Note! The pre-2.6.12 function might not do enough to sure consistency 677 * when any of the pages in the range is already mapped. 678 */ 680 679 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12) 681 682 680 if (mapping) 681 invalidate_inode_pages2_range(mapping, offStart >> PAGE_SHIFT, (offEnd - 1) >> PAGE_SHIFT); 683 682 # elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 60) 684 685 683 if (mapping && mapping->nrpages > 0) 684 invalidate_mapping_pages(mapping, offStart >> PAGE_SHIFT, (offEnd - 1) >> PAGE_SHIFT); 686 685 # else 687 688 686 /** @todo ... */ 687 RT_NOREF(mapping, offStart, offEnd); 689 688 # endif 690 689 } … … 696 695 */ 697 696 static ssize_t sf_reg_write_fallback(struct file *file, const char /*__user*/ *buf, size_t size, loff_t *off, loff_t offFile, 698 699 700 { 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 697 struct inode *inode, struct sf_inode_info *sf_i, 698 struct vbsf_super_info *sf_g, struct sf_reg_info *sf_r) 699 { 700 /* 701 * Lock pages and execute the write, taking care not to pass the host 702 * more than it can handle in one go or more than we care to allocate 703 * page arrays for. The latter limit is set at just short of 32KB due 704 * to how the physical heap works. 705 */ 706 struct page *apPagesStack[16]; 707 struct page **papPages = &apPagesStack[0]; 708 struct page **papPagesFree = NULL; 709 VBOXSFWRITEPGLSTREQ *pReq; 710 ssize_t cbRet = -ENOMEM; 711 size_t cPages = (((uintptr_t)buf & PAGE_OFFSET_MASK) + size + PAGE_OFFSET_MASK) >> PAGE_SHIFT; 712 size_t cMaxPages = RT_MIN(RT_MAX(sf_g->cMaxIoPages, 1), cPages); 713 714 pReq = (VBOXSFWRITEPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFWRITEPGLSTREQ, PgLst.aPages[cMaxPages])); 715 while (!pReq && cMaxPages > 4) { 716 cMaxPages /= 2; 717 pReq = (VBOXSFWRITEPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFWRITEPGLSTREQ, PgLst.aPages[cMaxPages])); 718 } 719 if (pReq && cPages > RT_ELEMENTS(apPagesStack)) 720 papPagesFree = papPages = kmalloc(cMaxPages * sizeof(sizeof(papPages[0])), GFP_KERNEL); 721 if (pReq && papPages) { 722 cbRet = 0; 723 for (;;) { 724 /* 725 * Figure out how much to process now and lock the user pages. 726 */ 727 int rc; 728 size_t cbChunk = (uintptr_t)buf & PAGE_OFFSET_MASK; 729 pReq->PgLst.offFirstPage = (uint16_t)cbChunk; 730 cPages = RT_ALIGN_Z(cbChunk + size, PAGE_SIZE) >> PAGE_SHIFT; 731 if (cPages <= cMaxPages) 732 cbChunk = size; 733 else { 734 cPages = cMaxPages; 735 cbChunk = (cMaxPages << PAGE_SHIFT) - cbChunk; 736 } 737 738 rc = sf_lock_user_pages((uintptr_t)buf, cPages, false /*fWrite*/, papPages); 739 if (rc == 0) { 740 size_t iPage = cPages; 741 while (iPage-- > 0) 742 pReq->PgLst.aPages[iPage] = page_to_phys(papPages[iPage]); 743 } else { 744 cbRet = rc; 745 break; 746 } 747 748 /* 749 * Issue the request and unlock the pages. 750 */ 751 rc = VbglR0SfHostReqWritePgLst(sf_g->map.root, pReq, sf_r->Handle.hHost, offFile, cbChunk, cPages); 752 753 sf_unlock_user_pages(papPages, cPages, false /*fSetDirty*/); 754 755 if (RT_SUCCESS(rc)) { 756 /* 757 * Success, advance position and buffer. 758 */ 759 uint32_t cbActual = pReq->Parms.cb32Write.u.value32; 760 AssertStmt(cbActual <= cbChunk, cbActual = cbChunk); 761 cbRet += cbActual; 762 offFile += cbActual; 763 buf = (uint8_t *)buf + cbActual; 764 size -= cbActual; 765 if (offFile > i_size_read(inode)) 766 i_size_write(inode, offFile); 767 sf_reg_write_invalidate_mapping_range(inode->i_mapping, offFile - cbActual, offFile); 768 769 /* 770 * Are we done already? If so commit the new file offset. 771 */ 772 if (!size || cbActual < cbChunk) { 773 *off = offFile; 774 break; 775 } 776 } else if (rc == VERR_NO_MEMORY && cMaxPages > 4) { 777 /* 778 * The host probably doesn't have enough heap to handle the 779 * request, reduce the page count and retry. 780 */ 781 cMaxPages /= 4; 782 Assert(cMaxPages > 0); 783 } else { 784 /* 785 * If we've successfully written stuff, return it rather than 786 * the error. (Not sure if this is such a great idea...) 787 */ 788 if (cbRet > 0) 789 *off = offFile; 790 else 791 cbRet = -EPROTO; 792 break; 793 } 794 sf_i->force_restat = 1; /* mtime (and size) may have changed */ 795 } 796 } 797 if (papPagesFree) 798 kfree(papPages); 799 if (pReq) 800 VbglR0PhysHeapFree(pReq); 801 return cbRet; 803 802 } 804 803 … … 814 813 */ 815 814 static ssize_t sf_reg_write(struct file *file, const char *buf, size_t size, 816 817 { 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 815 loff_t * off) 816 { 817 struct inode *inode = GET_F_DENTRY(file)->d_inode; 818 struct sf_inode_info *sf_i = GET_INODE_INFO(inode); 819 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb); 820 struct sf_reg_info *sf_r = file->private_data; 821 struct address_space *mapping = inode->i_mapping; 822 loff_t pos; 823 824 SFLOGFLOW(("sf_reg_write: inode=%p file=%p buf=%p size=%#zx off=%#llx\n", inode, file, buf, size, *off)); 825 BUG_ON(!sf_i); 826 BUG_ON(!sf_g); 827 BUG_ON(!sf_r); 828 829 if (!S_ISREG(inode->i_mode)) { 830 LogFunc(("write to non regular file %d\n", inode->i_mode)); 831 return -EINVAL; 832 } 833 834 pos = *off; 835 /** @todo This should be handled by the host, it returning the new file 836 * offset when appending. We may have an outdated i_size value here! */ 837 if (file->f_flags & O_APPEND) 838 pos = i_size_read(inode); 839 840 /** @todo XXX Check write permission according to inode->i_mode! */ 841 842 if (!size) { 843 if (file->f_flags & O_APPEND) /** @todo check if this is the consensus behavior... */ 844 *off = pos; 845 return 0; 846 } 847 848 /* 849 * If there are active writable mappings, coordinate with any 850 * pending writes via those. 851 */ 852 if ( mapping 853 && mapping->nrpages > 0 854 && mapping_writably_mapped(mapping)) { 856 855 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) 857 858 859 856 int err = filemap_fdatawait_range(mapping, pos, pos + size - 1); 857 if (err) 858 return err; 860 859 #else 861 862 #endif 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 860 /** @todo ... */ 861 #endif 862 } 863 864 /* 865 * For small requests, try use an embedded buffer provided we get a heap block 866 * that does not cross page boundraries (see host code). 867 */ 868 if (size <= PAGE_SIZE / 4 * 3 - RT_UOFFSETOF(VBOXSFWRITEEMBEDDEDREQ, abData[0]) /* see allocator */) { 869 uint32_t const cbReq = RT_UOFFSETOF(VBOXSFWRITEEMBEDDEDREQ, abData[0]) + size; 870 VBOXSFWRITEEMBEDDEDREQ *pReq = (VBOXSFWRITEEMBEDDEDREQ *)VbglR0PhysHeapAlloc(cbReq); 871 if ( pReq 872 && (PAGE_SIZE - ((uintptr_t)pReq & PAGE_OFFSET_MASK)) >= cbReq) { 873 ssize_t cbRet; 874 if (copy_from_user(pReq->abData, buf, size) == 0) { 875 int vrc = VbglR0SfHostReqWriteEmbedded(sf_g->map.root, pReq, sf_r->Handle.hHost, 876 pos, (uint32_t)size); 877 if (RT_SUCCESS(vrc)) { 878 cbRet = pReq->Parms.cb32Write.u.value32; 879 AssertStmt(cbRet <= (ssize_t)size, cbRet = size); 880 pos += cbRet; 881 *off = pos; 882 if (pos > i_size_read(inode)) 883 i_size_write(inode, pos); 884 sf_reg_write_invalidate_mapping_range(mapping, pos - cbRet, pos); 885 } else 886 cbRet = -EPROTO; 887 sf_i->force_restat = 1; /* mtime (and size) may have changed */ 888 } else 889 cbRet = -EFAULT; 890 891 VbglR0PhysHeapFree(pReq); 892 return cbRet; 893 } 894 if (pReq) 895 VbglR0PhysHeapFree(pReq); 896 } 898 897 899 898 #if 0 /* Turns out this is slightly slower than locking the pages even for 4KB reads (4.19/amd64). */ 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 #endif 935 936 899 /* 900 * For medium sized requests try use a bounce buffer. 901 */ 902 if (size <= _64K /** @todo make this configurable? */) { 903 void *pvBounce = kmalloc(size, GFP_KERNEL); 904 if (pvBounce) { 905 if (copy_from_user(pvBounce, buf, size) == 0) { 906 VBOXSFWRITEPGLSTREQ *pReq = (VBOXSFWRITEPGLSTREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq)); 907 if (pReq) { 908 ssize_t cbRet; 909 int vrc = VbglR0SfHostReqWriteContig(sf_g->map.root, pReq, sf_r->handle, pos, 910 (uint32_t)size, pvBounce, virt_to_phys(pvBounce)); 911 if (RT_SUCCESS(vrc)) { 912 cbRet = pReq->Parms.cb32Write.u.value32; 913 AssertStmt(cbRet <= (ssize_t)size, cbRet = size); 914 pos += cbRet; 915 *off = pos; 916 if (pos > i_size_read(inode)) 917 i_size_write(inode, pos); 918 sf_reg_write_invalidate_mapping_range(mapping, pos - cbRet, pos); 919 } else 920 cbRet = -EPROTO; 921 sf_i->force_restat = 1; /* mtime (and size) may have changed */ 922 VbglR0PhysHeapFree(pReq); 923 kfree(pvBounce); 924 return cbRet; 925 } 926 kfree(pvBounce); 927 } else { 928 kfree(pvBounce); 929 return -EFAULT; 930 } 931 } 932 } 933 #endif 934 935 return sf_reg_write_fallback(file, buf, size, off, pos, inode, sf_i, sf_g, sf_r); 937 936 } 938 937 … … 947 946 static int sf_reg_open(struct inode *inode, struct file *file) 948 947 { 949 950 951 952 948 int rc, rc_linux = 0; 949 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb); 950 struct sf_inode_info *sf_i = GET_INODE_INFO(inode); 951 struct sf_reg_info *sf_r; 953 952 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) 954 953 struct dentry *dentry = file_dentry(file); 955 954 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) 956 955 struct dentry *dentry = file->f_path.dentry; 957 956 #else 958 959 #endif 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 957 struct dentry *dentry = file->f_dentry; 958 #endif 959 VBOXSFCREATEREQ *pReq; 960 SHFLCREATEPARMS *pCreateParms; /* temp glue */ 961 962 SFLOGFLOW(("sf_reg_open: inode=%p file=%p flags=%#x %s\n", 963 inode, file, file->f_flags, sf_i ? sf_i->path->String.ach : NULL)); 964 BUG_ON(!sf_g); 965 BUG_ON(!sf_i); 966 967 sf_r = kmalloc(sizeof(*sf_r), GFP_KERNEL); 968 if (!sf_r) { 969 LogRelFunc(("could not allocate reg info\n")); 970 return -ENOMEM; 971 } 972 973 RTListInit(&sf_r->Handle.Entry); 974 sf_r->Handle.cRefs = 1; 975 sf_r->Handle.fFlags = SF_HANDLE_F_FILE | SF_HANDLE_F_MAGIC; 976 sf_r->Handle.hHost = SHFL_HANDLE_NIL; 977 978 /* Already open? */ 979 if (sf_i->handle != SHFL_HANDLE_NIL) { 980 /* 981 * This inode was created with sf_create_aux(). Check the CreateFlags: 982 * O_CREAT, O_TRUNC: inherent true (file was just created). Not sure 983 * about the access flags (SHFL_CF_ACCESS_*). 984 */ 985 sf_i->force_restat = 1; 986 sf_r->Handle.hHost = sf_i->handle; 987 sf_i->handle = SHFL_HANDLE_NIL; 988 file->private_data = sf_r; 989 990 sf_r->Handle.fFlags |= SF_HANDLE_F_READ | SF_HANDLE_F_WRITE; /** @todo check */ 991 sf_handle_append(sf_i, &sf_r->Handle); 992 SFLOGFLOW(("sf_reg_open: returns 0 (#1) - sf_i=%p hHost=%#llx\n", sf_i, sf_r->Handle.hHost)); 993 return 0; 994 } 995 996 pReq = (VBOXSFCREATEREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq) + sf_i->path->u16Size); 997 if (!pReq) { 998 kfree(sf_r); 999 LogRelFunc(("Failed to allocate a VBOXSFCREATEREQ buffer!\n")); 1000 return -ENOMEM; 1001 } 1002 memcpy(&pReq->StrPath, sf_i->path, SHFLSTRING_HEADER_SIZE + sf_i->path->u16Size); 1003 RT_ZERO(pReq->CreateParms); 1004 pCreateParms = &pReq->CreateParms; 1005 pCreateParms->Handle = SHFL_HANDLE_NIL; 1006 1007 /* We check the value of pCreateParms->Handle afterwards to find out if 1008 * the call succeeded or failed, as the API does not seem to cleanly 1009 * distinguish error and informational messages. 1010 * 1011 * Furthermore, we must set pCreateParms->Handle to SHFL_HANDLE_NIL to 1012 * make the shared folders host service use our fMode parameter */ 1013 1014 if (file->f_flags & O_CREAT) { 1015 LogFunc(("O_CREAT set\n")); 1016 pCreateParms->CreateFlags |= SHFL_CF_ACT_CREATE_IF_NEW; 1017 /* We ignore O_EXCL, as the Linux kernel seems to call create 1018 beforehand itself, so O_EXCL should always fail. */ 1019 if (file->f_flags & O_TRUNC) { 1020 LogFunc(("O_TRUNC set\n")); 1021 pCreateParms->CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; 1022 } else 1023 pCreateParms->CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS; 1024 } else { 1025 pCreateParms->CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW; 1026 if (file->f_flags & O_TRUNC) { 1027 LogFunc(("O_TRUNC set\n")); 1028 pCreateParms->CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; 1029 } 1030 } 1031 1032 switch (file->f_flags & O_ACCMODE) { 1033 case O_RDONLY: 1034 pCreateParms->CreateFlags |= SHFL_CF_ACCESS_READ; 1035 sf_r->Handle.fFlags |= SF_HANDLE_F_READ; 1036 break; 1037 1038 case O_WRONLY: 1039 pCreateParms->CreateFlags |= SHFL_CF_ACCESS_WRITE; 1040 sf_r->Handle.fFlags |= SF_HANDLE_F_WRITE; 1041 break; 1042 1043 case O_RDWR: 1044 pCreateParms->CreateFlags |= SHFL_CF_ACCESS_READWRITE; 1045 sf_r->Handle.fFlags |= SF_HANDLE_F_READ | SF_HANDLE_F_WRITE; 1046 break; 1047 1048 default: 1049 BUG(); 1050 } 1051 1052 if (file->f_flags & O_APPEND) { 1053 LogFunc(("O_APPEND set\n")); 1054 pCreateParms->CreateFlags |= SHFL_CF_ACCESS_APPEND; 1055 sf_r->Handle.fFlags |= SF_HANDLE_F_APPEND; 1056 } 1057 1058 pCreateParms->Info.Attr.fMode = inode->i_mode; 1059 LogFunc(("sf_reg_open: calling VbglR0SfHostReqCreate, file %s, flags=%#x, %#x\n", sf_i->path->String.utf8, file->f_flags, pCreateParms->CreateFlags)); 1060 rc = VbglR0SfHostReqCreate(sf_g->map.root, pReq); 1061 if (RT_FAILURE(rc)) { 1062 LogFunc(("VbglR0SfHostReqCreate failed flags=%d,%#x rc=%Rrc\n", file->f_flags, pCreateParms->CreateFlags, rc)); 1063 kfree(sf_r); 1064 VbglR0PhysHeapFree(pReq); 1065 return -RTErrConvertToErrno(rc); 1066 } 1067 1068 if (pCreateParms->Handle != SHFL_HANDLE_NIL) { 1069 sf_dentry_chain_increase_ttl(dentry); 1070 rc_linux = 0; 1071 } else { 1072 switch (pCreateParms->Result) { 1073 case SHFL_PATH_NOT_FOUND: 1074 rc_linux = -ENOENT; 1075 break; 1076 case SHFL_FILE_NOT_FOUND: 1077 /** @todo sf_dentry_increase_parent_ttl(file->f_dentry); if we can trust it. */ 1078 rc_linux = -ENOENT; 1079 break; 1080 case SHFL_FILE_EXISTS: 1081 sf_dentry_chain_increase_ttl(dentry); 1082 rc_linux = -EEXIST; 1083 break; 1084 default: 1085 sf_dentry_chain_increase_parent_ttl(dentry); 1086 rc_linux = 0; 1087 break; 1088 } 1089 } 1090 1091 sf_i->force_restat = 1; /** @todo Why?!? */ 1092 sf_r->Handle.hHost = pCreateParms->Handle; 1093 file->private_data = sf_r; 1094 sf_handle_append(sf_i, &sf_r->Handle); 1095 VbglR0PhysHeapFree(pReq); 1096 SFLOGFLOW(("sf_reg_open: returns 0 (#2) - sf_i=%p hHost=%#llx\n", sf_i, sf_r->Handle.hHost)); 1097 return rc_linux; 1099 1098 } 1100 1099 … … 1109 1108 static int sf_reg_release(struct inode *inode, struct file *file) 1110 1109 { 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1110 struct sf_reg_info *sf_r; 1111 struct vbsf_super_info *sf_g; 1112 struct sf_inode_info *sf_i = GET_INODE_INFO(inode); 1113 1114 SFLOGFLOW(("sf_reg_release: inode=%p file=%p\n", inode, file)); 1115 sf_g = VBSF_GET_SUPER_INFO(inode->i_sb); 1116 sf_r = file->private_data; 1117 1118 BUG_ON(!sf_g); 1119 BUG_ON(!sf_r); 1121 1120 1122 1121 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) 1123 1124 1125 1126 1127 1128 1129 1130 1131 #endif 1132 1133 1134 1135 1136 1137 1138 1122 /* See the smbfs source (file.c). mmap in particular can cause data to be 1123 * written to the file after it is closed, which we can't cope with. We 1124 * copy and paste the body of filemap_write_and_wait() here as it was not 1125 * defined before 2.6.6 and not exported until quite a bit later. */ 1126 /* filemap_write_and_wait(inode->i_mapping); */ 1127 if (inode->i_mapping->nrpages 1128 && filemap_fdatawrite(inode->i_mapping) != -EIO) 1129 filemap_fdatawait(inode->i_mapping); 1130 #endif 1131 1132 /* Release sf_r, closing the handle if we're the last user. */ 1133 file->private_data = NULL; 1134 sf_handle_release(&sf_r->Handle, sf_g, "sf_reg_release"); 1135 1136 sf_i->handle = SHFL_HANDLE_NIL; 1137 return 0; 1139 1138 } 1140 1139 … … 1150 1149 static loff_t sf_reg_llseek(struct file *file, loff_t off, int whence) 1151 1150 { 1152 1153 1154 1151 SFLOGFLOW(("sf_reg_llseek: file=%p off=%lld whence=%d\n", file, off, whence)); 1152 1153 switch (whence) { 1155 1154 #ifdef SEEK_HOLE 1156 1157 1158 #endif 1159 1160 1161 1162 1163 1164 1165 1166 1167 1155 case SEEK_HOLE: 1156 case SEEK_DATA: 1157 #endif 1158 case SEEK_END: { 1159 struct sf_reg_info *sf_r = file->private_data; 1160 int rc = sf_inode_revalidate_with_handle(GET_F_DENTRY(file), sf_r->Handle.hHost, true /*fForce*/, 1161 false /*fInodeLocked*/); 1162 if (rc == 0) 1163 break; 1164 return rc; 1165 } 1166 } 1168 1167 1169 1168 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 8) 1170 1169 return generic_file_llseek(file, off, whence); 1171 1170 #else 1172 1171 return default_llseek(file, off, whence); 1173 1172 #endif 1174 1173 } … … 1186 1185 { 1187 1186 # if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) 1188 1187 return __generic_file_fsync(file, start, end, datasync); 1189 1188 # else 1190 1189 return generic_file_fsync(file, start, end, datasync); 1191 1190 # endif 1192 1191 } … … 1194 1193 static int sf_reg_fsync(struct file *file, int datasync) 1195 1194 { 1196 1195 return generic_file_fsync(file, datasync); 1197 1196 } 1198 1197 #else /* < 2.6.35 */ … … 1200 1199 { 1201 1200 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) 1202 1201 return simple_fsync(file, dentry, datasync); 1203 1202 # else 1204 1205 1206 1207 1208 1203 int rc; 1204 struct inode *inode = dentry->d_inode; 1205 AssertReturn(inode, -EINVAL); 1206 1207 /** @todo What about file_fsync()? (<= 2.5.11) */ 1209 1208 1210 1209 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 12) 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1210 rc = sync_mapping_buffers(inode->i_mapping); 1211 if ( rc == 0 1212 && (inode->i_state & I_DIRTY) 1213 && ((inode->i_state & I_DIRTY_DATASYNC) || !datasync) 1214 ) { 1215 struct writeback_control wbc = { 1216 .sync_mode = WB_SYNC_ALL, 1217 .nr_to_write = 0 1218 }; 1219 rc = sync_inode(inode, &wbc); 1220 } 1222 1221 # else /* < 2.5.12 */ 1223 1222 rc = fsync_inode_buffers(inode); 1224 1223 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 10) 1225 1224 rc |= fsync_inode_data_buffers(inode); 1226 1225 # endif 1227 1226 /** @todo probably need to do more here... */ 1228 1227 # endif /* < 2.5.12 */ 1229 1228 return rc; 1230 1229 # endif 1231 1230 } … … 1234 1233 1235 1234 struct file_operations sf_reg_fops = { 1236 1237 1238 1239 1240 1235 .read = sf_reg_read, 1236 .open = sf_reg_open, 1237 .write = sf_reg_write, 1238 .release = sf_reg_release, 1239 .mmap = generic_file_mmap, 1241 1240 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) 1242 1241 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) … … 1244 1243 * cached. Investigate. */ 1245 1244 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) 1246 1245 .splice_read = sf_splice_read, 1247 1246 # else 1248 1247 .sendfile = generic_file_sendfile, 1249 1248 # endif 1250 1251 1249 .aio_read = generic_file_aio_read, 1250 .aio_write = generic_file_aio_write, 1252 1251 # endif 1253 1252 #endif 1254 1255 1253 .llseek = sf_reg_llseek, 1254 .fsync = sf_reg_fsync, 1256 1255 }; 1257 1256 1258 1257 struct inode_operations sf_reg_iops = { 1259 1258 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) 1260 1259 .revalidate = sf_inode_revalidate 1261 1260 #else 1262 1263 1261 .getattr = sf_getattr, 1262 .setattr = sf_setattr 1264 1263 #endif 1265 1264 }; … … 1275 1274 static int sf_readpage(struct file *file, struct page *page) 1276 1275 { 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 uint32_tcbRead;1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1276 struct inode *inode = GET_F_DENTRY(file)->d_inode; 1277 int err; 1278 1279 SFLOGFLOW(("sf_readpage: inode=%p file=%p page=%p off=%#llx\n", inode, file, page, (uint64_t)page->index << PAGE_SHIFT)); 1280 1281 if (!is_bad_inode(inode)) { 1282 VBOXSFREADPGLSTREQ *pReq = (VBOXSFREADPGLSTREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq)); 1283 if (pReq) { 1284 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb); 1285 struct sf_reg_info *sf_r = file->private_data; 1286 uint32_t cbRead; 1287 int vrc; 1288 1289 pReq->PgLst.offFirstPage = 0; 1290 pReq->PgLst.aPages[0] = page_to_phys(page); 1291 vrc = VbglR0SfHostReqReadPgLst(sf_g->map.root, 1292 pReq, 1293 sf_r->Handle.hHost, 1294 (uint64_t)page->index << PAGE_SHIFT, 1295 PAGE_SIZE, 1296 1 /*cPages*/); 1297 1298 cbRead = pReq->Parms.cb32Read.u.value32; 1299 AssertStmt(cbRead <= PAGE_SIZE, cbRead = PAGE_SIZE); 1300 VbglR0PhysHeapFree(pReq); 1301 1302 if (RT_SUCCESS(vrc)) { 1303 if (cbRead == PAGE_SIZE) { 1304 /* likely */ 1305 } else { 1306 uint8_t *pbMapped = (uint8_t *)kmap(page); 1307 RT_BZERO(&pbMapped[cbRead], PAGE_SIZE - cbRead); 1308 kunmap(page); 1309 /** @todo truncate the inode file size? */ 1310 } 1311 1312 flush_dcache_page(page); 1313 SetPageUptodate(page); 1314 err = 0; 1315 } else 1316 err = -EPROTO; 1317 } else 1318 err = -ENOMEM; 1319 } else 1320 err = -EIO; 1321 unlock_page(page); 1322 return err; 1324 1323 } 1325 1324 … … 1333 1332 static int sf_writepage(struct page *page, struct writeback_control *wbc) 1334 1333 { 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1334 struct address_space *mapping = page->mapping; 1335 struct inode *inode = mapping->host; 1336 struct sf_inode_info *sf_i = GET_INODE_INFO(inode); 1337 struct sf_handle *pHandle = sf_handle_find(sf_i, SF_HANDLE_F_WRITE, SF_HANDLE_F_APPEND); 1338 int err; 1339 1340 SFLOGFLOW(("sf_writepage: inode=%p page=%p off=%#llx pHandle=%p (%#llx)\n", 1341 inode, page,(uint64_t)page->index << PAGE_SHIFT, pHandle, pHandle->hHost)); 1342 1343 if (pHandle) { 1344 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb); 1345 VBOXSFWRITEPGLSTREQ *pReq = (VBOXSFWRITEPGLSTREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq)); 1346 if (pReq) { 1347 uint64_t const cbFile = i_size_read(inode); 1348 uint64_t const offInFile = (uint64_t)page->index << PAGE_SHIFT; 1349 uint32_t const cbToWrite = page->index != (cbFile >> PAGE_SHIFT) ? PAGE_SIZE 1350 : (uint32_t)cbFile & (uint32_t)PAGE_OFFSET_MASK; 1351 int vrc; 1352 1353 pReq->PgLst.offFirstPage = 0; 1354 pReq->PgLst.aPages[0] = page_to_phys(page); 1355 vrc = VbglR0SfHostReqWritePgLst(sf_g->map.root, 1356 pReq, 1357 pHandle->hHost, 1358 offInFile, 1359 cbToWrite, 1360 1 /*cPages*/); 1361 AssertMsgStmt(pReq->Parms.cb32Write.u.value32 == cbToWrite || RT_FAILURE(vrc), /* lazy bird */ 1362 ("%#x vs %#x\n", pReq->Parms.cb32Write, cbToWrite), 1363 vrc = VERR_WRITE_ERROR); 1364 VbglR0PhysHeapFree(pReq); 1365 1366 if (RT_SUCCESS(vrc)) { 1367 /* Update the inode if we've extended the file. */ 1368 /** @todo is this necessary given the cbToWrite calc above? */ 1369 uint64_t const offEndOfWrite = offInFile + cbToWrite; 1370 if ( offEndOfWrite > cbFile 1371 && offEndOfWrite > i_size_read(inode)) 1372 i_size_write(inode, offEndOfWrite); 1373 1374 if (PageError(page)) 1375 ClearPageError(page); 1376 1377 err = 0; 1378 } else { 1379 ClearPageUptodate(page); 1380 err = -EPROTO; 1381 } 1382 } else 1383 err = -ENOMEM; 1384 sf_handle_release(pHandle, sf_g, "sf_writepage"); 1385 } else { 1386 static uint64_t volatile s_cCalls = 0; 1387 if (s_cCalls++ < 16) 1388 printk("sf_writepage: no writable handle for %s..\n", sf_i->path->String.ach); 1389 err = -EPROTO; 1390 } 1391 unlock_page(page); 1392 return err; 1394 1393 } 1395 1394 … … 1399 1398 */ 1400 1399 int sf_write_begin(struct file *file, struct address_space *mapping, loff_t pos, 1401 1402 1403 { 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1400 unsigned len, unsigned flags, struct page **pagep, 1401 void **fsdata) 1402 { 1403 /** @todo r=bird: We shouldn't ever get here, should we? Because we don't use 1404 * the page cache for any writes AFAIK. We could just as well use 1405 * simple_write_begin & simple_write_end here if we think we really 1406 * need to have non-NULL function pointers in the table... */ 1407 static uint64_t volatile s_cCalls = 0; 1408 if (s_cCalls++ < 16) { 1409 printk("vboxsf: Unexpected call to sf_write_begin(pos=%#llx len=%#x flags=%#x)! Please report.\n", 1410 (unsigned long long)pos, len, flags); 1411 RTLogBackdoorPrintf("vboxsf: Unexpected call to sf_write_begin(pos=%#llx len=%#x flags=%#x)! Please report.\n", 1412 (unsigned long long)pos, len, flags); 1414 1413 # ifdef WARN_ON 1415 1414 WARN_ON(1); 1416 1415 # endif 1417 1418 1419 } 1420 # endif 1416 } 1417 return simple_write_begin(file, mapping, pos, len, flags, pagep, fsdata); 1418 } 1419 # endif /* KERNEL_VERSION >= 2.6.24 */ 1421 1420 1422 1421 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 10) … … 1445 1444 # endif 1446 1445 { 1447 1448 1446 TRACE(); 1447 return -EINVAL; 1449 1448 } 1450 1449 # endif 1451 1450 1452 1451 struct address_space_operations sf_reg_aops = { 1453 1454 1455 1452 .readpage = sf_readpage, 1453 .writepage = sf_writepage, 1454 /** @todo Need .writepages if we want msync performance... */ 1456 1455 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 12) 1457 1456 .set_page_dirty = __set_page_dirty_buffers, 1458 1457 # endif 1459 1458 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) 1460 1461 1459 .write_begin = sf_write_begin, 1460 .write_end = simple_write_end, 1462 1461 # else 1463 1464 1462 .prepare_write = simple_prepare_write, 1463 .commit_write = simple_commit_write, 1465 1464 # endif 1466 1465 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 10) 1467 1466 .direct_IO = sf_direct_IO, 1468 1467 # endif 1469 1468 }; -
trunk/src/VBox/Additions/linux/sharedfolders/utils.c
r77524 r77526 43 43 DECLINLINE(void) sf_ftime_from_timespec(time_t *pLinuxDst, PCRTTIMESPEC pVBoxSrc) 44 44 { 45 46 47 48 } 49 #else 45 int64_t t = RTTimeSpecGetNano(pVBoxSrc); 46 do_div(t, RT_NS_1SEC); 47 *pLinuxDst = t; 48 } 49 #else /* >= 2.6.0 */ 50 50 # if LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0) 51 51 DECLINLINE(void) sf_ftime_from_timespec(struct timespec *pLinuxDst, PCRTTIMESPEC pVBoxSrc) … … 54 54 # endif 55 55 { 56 57 58 59 } 60 #endif 56 int64_t t = RTTimeSpecGetNano(pVBoxSrc); 57 pLinuxDst->tv_nsec = do_div(t, RT_NS_1SEC); 58 pLinuxDst->tv_sec = t; 59 } 60 #endif /* >= 2.6.0 */ 61 61 62 62 … … 67 67 DECLINLINE(void) sf_timespec_from_ftime(PRTTIMESPEC pVBoxDst, time_t *pLinuxSrc) 68 68 { 69 70 } 71 #else 69 RTTimeSpecSetNano(pVBoxDst, RT_NS_1SEC_64 * *pLinuxSrc); 70 } 71 #else /* >= 2.6.0 */ 72 72 # if LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0) 73 73 DECLINLINE(void) sf_timespec_from_ftime(PRTTIMESPEC pVBoxDst, struct timespec const *pLinuxSrc) … … 76 76 # endif 77 77 { 78 79 } 80 #endif 78 RTTimeSpecSetNano(pVBoxDst, pLinuxSrc->tv_nsec + pLinuxSrc->tv_sec * (int64_t)RT_NS_1SEC); 79 } 80 #endif /* >= 2.6.0 */ 81 81 82 82 … … 88 88 DECLINLINE(int) sf_convert_access_perms(uint32_t fAttr) 89 89 { 90 91 92 93 94 95 96 97 98 99 100 101 90 /* Access bits should be the same: */ 91 AssertCompile(RTFS_UNIX_IRUSR == S_IRUSR); 92 AssertCompile(RTFS_UNIX_IWUSR == S_IWUSR); 93 AssertCompile(RTFS_UNIX_IXUSR == S_IXUSR); 94 AssertCompile(RTFS_UNIX_IRGRP == S_IRGRP); 95 AssertCompile(RTFS_UNIX_IWGRP == S_IWGRP); 96 AssertCompile(RTFS_UNIX_IXGRP == S_IXGRP); 97 AssertCompile(RTFS_UNIX_IROTH == S_IROTH); 98 AssertCompile(RTFS_UNIX_IWOTH == S_IWOTH); 99 AssertCompile(RTFS_UNIX_IXOTH == S_IXOTH); 100 101 return fAttr & RTFS_UNIX_ALL_ACCESS_PERMS; 102 102 } 103 103 … … 108 108 DECLINLINE(int) sf_convert_file_mode(uint32_t fVBoxMode, int fFixedMode, int fClearMask, int fType) 109 109 { 110 111 112 113 114 115 110 int fLnxMode = sf_convert_access_perms(fVBoxMode); 111 if (fFixedMode != ~0) 112 fLnxMode = fFixedMode & 0777; 113 fLnxMode &= ~fClearMask; 114 fLnxMode |= fType; 115 return fLnxMode; 116 116 } 117 117 … … 122 122 void sf_init_inode(struct inode *inode, struct sf_inode_info *sf_i, PSHFLFSOBJINFO pObjInfo, struct vbsf_super_info *sf_g) 123 123 { 124 125 126 127 128 129 124 PCSHFLFSOBJATTR pAttr = &pObjInfo->Attr; 125 126 TRACE(); 127 128 sf_i->ts_up_to_date = jiffies; 129 sf_i->force_restat = 0; 130 130 131 131 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) 132 132 inode->i_mapping->a_ops = &sf_reg_aops; 133 133 # if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19, 0) 134 134 inode->i_mapping->backing_dev_info = &sf_g->bdi; /* This is needed for mmap. */ 135 135 # endif 136 136 #endif 137 138 139 140 141 142 143 144 145 137 if (RTFS_IS_DIRECTORY(pAttr->fMode)) { 138 inode->i_mode = sf_convert_file_mode(pAttr->fMode, sf_g->dmode, sf_g->dmask, S_IFDIR); 139 inode->i_op = &sf_dir_iops; 140 inode->i_fop = &sf_dir_fops; 141 142 /* XXX: this probably should be set to the number of entries 143 in the directory plus two (. ..) */ 144 set_nlink(inode, 1); 145 } 146 146 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8) 147 148 149 150 151 152 153 154 #endif 155 156 157 158 159 160 147 else if (RTFS_IS_SYMLINK(pAttr->fMode)) { 148 /** @todo r=bird: Aren't System V symlinks w/o any mode mask? IIRC there is 149 * no lchmod on Linux. */ 150 inode->i_mode = sf_convert_file_mode(pAttr->fMode, sf_g->fmode, sf_g->fmask, S_IFLNK); 151 inode->i_op = &sf_lnk_iops; 152 set_nlink(inode, 1); 153 } 154 #endif 155 else { 156 inode->i_mode = sf_convert_file_mode(pAttr->fMode, sf_g->fmode, sf_g->fmask, S_IFREG); 157 inode->i_op = &sf_reg_iops; 158 inode->i_fop = &sf_reg_fops; 159 set_nlink(inode, 1); 160 } 161 161 162 162 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) 163 164 163 inode->i_uid = make_kuid(current_user_ns(), sf_g->uid); 164 inode->i_gid = make_kgid(current_user_ns(), sf_g->gid); 165 165 #else 166 167 168 #endif 169 170 166 inode->i_uid = sf_g->uid; 167 inode->i_gid = sf_g->gid; 168 #endif 169 170 inode->i_size = pObjInfo->cbObject; 171 171 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) && !defined(KERNEL_FC6) 172 172 inode->i_blksize = 4096; 173 173 #endif 174 174 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 11) 175 176 #endif 177 178 179 180 181 182 183 175 inode->i_blkbits = 12; 176 #endif 177 /* i_blocks always in units of 512 bytes! */ 178 inode->i_blocks = (pObjInfo->cbAllocated + 511) / 512; 179 180 sf_ftime_from_timespec(&inode->i_atime, &pObjInfo->AccessTime); 181 sf_ftime_from_timespec(&inode->i_ctime, &pObjInfo->ChangeTime); 182 sf_ftime_from_timespec(&inode->i_mtime, &pObjInfo->ModificationTime); 183 sf_i->BirthTime = pObjInfo->BirthTime; 184 184 } 185 185 … … 193 193 */ 194 194 static void sf_update_inode(struct inode *pInode, struct sf_inode_info *pInodeInfo, PSHFLFSOBJINFO pObjInfo, 195 196 { 197 198 199 200 195 struct vbsf_super_info *sf_g, bool fInodeLocked) 196 { 197 PCSHFLFSOBJATTR pAttr = &pObjInfo->Attr; 198 int fMode; 199 200 TRACE(); 201 201 202 202 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) 203 204 205 #endif 206 207 208 209 210 211 203 if (!fInodeLocked) 204 inode_lock(pInode); 205 #endif 206 207 /* 208 * Calc new mode mask and update it if it changed. 209 */ 210 if (RTFS_IS_DIRECTORY(pAttr->fMode)) 211 fMode = sf_convert_file_mode(pAttr->fMode, sf_g->dmode, sf_g->dmask, S_IFDIR); 212 212 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8) 213 214 215 216 217 #endif 218 219 220 221 222 223 224 225 226 227 228 229 230 213 else if (RTFS_IS_SYMLINK(pAttr->fMode)) 214 /** @todo r=bird: Aren't System V symlinks w/o any mode mask? IIRC there is 215 * no lchmod on Linux. */ 216 fMode = sf_convert_file_mode(pAttr->fMode, sf_g->fmode, sf_g->fmask, S_IFLNK); 217 #endif 218 else 219 fMode = sf_convert_file_mode(pAttr->fMode, sf_g->fmode, sf_g->fmask, S_IFREG); 220 221 if (fMode == pInode->i_mode) { 222 /* likely */ 223 } else { 224 if ((fMode & S_IFMT) == (pInode->i_mode & S_IFMT)) 225 pInode->i_mode = fMode; 226 else { 227 SFLOGFLOW(("sf_update_inode: Changed from %o to %o (%s)\n", 228 pInode->i_mode & S_IFMT, fMode & S_IFMT, pInodeInfo->path->String.ach)); 229 /** @todo we probably need to be more drastic... */ 230 sf_init_inode(pInode, pInodeInfo, pObjInfo, sf_g); 231 231 232 232 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) 233 234 235 #endif 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 233 if (!fInodeLocked) 234 inode_unlock(pInode); 235 #endif 236 return; 237 } 238 } 239 240 /* 241 * Update the sizes. 242 * Note! i_blocks is always in units of 512 bytes! 243 */ 244 pInode->i_blocks = (pObjInfo->cbAllocated + 511) / 512; 245 i_size_write(pInode, pObjInfo->cbObject); 246 247 /* 248 * Update the timestamps. 249 */ 250 sf_ftime_from_timespec(&pInode->i_atime, &pObjInfo->AccessTime); 251 sf_ftime_from_timespec(&pInode->i_ctime, &pObjInfo->ChangeTime); 252 sf_ftime_from_timespec(&pInode->i_mtime, &pObjInfo->ModificationTime); 253 pInodeInfo->BirthTime = pObjInfo->BirthTime; 254 255 /* 256 * Mark it as up to date. 257 */ 258 pInodeInfo->ts_up_to_date = jiffies; 259 pInodeInfo->force_restat = 0; 260 260 261 261 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) 262 263 262 if (!fInodeLocked) 263 inode_unlock(pInode); 264 264 #endif 265 265 } … … 268 268 /** @note Currently only used for the root directory during (re-)mount. */ 269 269 int sf_stat(const char *caller, struct vbsf_super_info *sf_g, 270 271 { 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 270 SHFLSTRING *path, PSHFLFSOBJINFO result, int ok_to_fail) 271 { 272 int rc; 273 VBOXSFCREATEREQ *pReq; 274 NOREF(caller); 275 276 TRACE(); 277 278 pReq = (VBOXSFCREATEREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq) + path->u16Size); 279 if (pReq) { 280 RT_ZERO(*pReq); 281 memcpy(&pReq->StrPath, path, SHFLSTRING_HEADER_SIZE + path->u16Size); 282 pReq->CreateParms.Handle = SHFL_HANDLE_NIL; 283 pReq->CreateParms.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW; 284 285 LogFunc(("Calling VbglR0SfHostReqCreate on %s\n", path->String.utf8)); 286 rc = VbglR0SfHostReqCreate(sf_g->map.root, pReq); 287 if (RT_SUCCESS(rc)) { 288 if (pReq->CreateParms.Result == SHFL_FILE_EXISTS) { 289 *result = pReq->CreateParms.Info; 290 rc = 0; 291 } else { 292 if (!ok_to_fail) 293 LogFunc(("VbglR0SfHostReqCreate on %s: file does not exist: %d (caller=%s)\n", 294 path->String.utf8, pReq->CreateParms.Result, caller)); 295 rc = -ENOENT; 296 } 297 } else if (rc == VERR_INVALID_NAME) { 298 rc = -ENOENT; /* this can happen for names like 'foo*' on a Windows host */ 299 } else { 300 LogFunc(("VbglR0SfHostReqCreate failed on %s: %Rrc (caller=%s)\n", path->String.utf8, rc, caller)); 301 rc = -EPROTO; 302 } 303 VbglR0PhysHeapFree(pReq); 304 } 305 else 306 rc = -ENOMEM; 307 return rc; 308 308 } 309 309 … … 315 315 int sf_inode_revalidate_worker(struct dentry *dentry, bool fForced) 316 316 { 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 317 int rc; 318 struct inode *pInode = dentry ? dentry->d_inode : NULL; 319 if (pInode) { 320 struct sf_inode_info *sf_i = GET_INODE_INFO(pInode); 321 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(pInode->i_sb); 322 AssertReturn(sf_i, -EINVAL); 323 AssertReturn(sf_g, -EINVAL); 324 325 /* 326 * Can we get away without any action here? 327 */ 328 if ( !fForced 329 && !sf_i->force_restat 330 && jiffies - sf_i->ts_up_to_date < sf_g->ttl) 331 rc = 0; 332 else { 333 /* 334 * No, we have to query the file info from the host. 335 * Try get a handle we can query, any kind of handle will do here. 336 */ 337 struct sf_handle *pHandle = sf_handle_find(sf_i, 0, 0); 338 if (pHandle) { 339 /* Query thru pHandle. */ 340 VBOXSFOBJINFOREQ *pReq = (VBOXSFOBJINFOREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq)); 341 if (pReq) { 342 RT_ZERO(*pReq); 343 rc = VbglR0SfHostReqQueryObjInfo(sf_g->map.root, pReq, pHandle->hHost); 344 if (RT_SUCCESS(rc)) { 345 /* 346 * Reset the TTL and copy the info over into the inode structure. 347 */ 348 sf_update_inode(pInode, sf_i, &pReq->ObjInfo, sf_g, true /*fInodeLocked??*/); 349 } else if (rc == VERR_INVALID_HANDLE) { 350 rc = -ENOENT; /* Restore.*/ 351 } else { 352 LogFunc(("VbglR0SfHostReqQueryObjInfo failed on %#RX64: %Rrc\n", pHandle->hHost, rc)); 353 rc = -RTErrConvertToErrno(rc); 354 } 355 VbglR0PhysHeapFree(pReq); 356 } else 357 rc = -ENOMEM; 358 sf_handle_release(pHandle, sf_g, "sf_inode_revalidate_worker"); 359 360 } else { 361 /* Query via path. */ 362 SHFLSTRING *pPath = sf_i->path; 363 VBOXSFCREATEREQ *pReq = (VBOXSFCREATEREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq) + pPath->u16Size); 364 if (pReq) { 365 RT_ZERO(*pReq); 366 memcpy(&pReq->StrPath, pPath, SHFLSTRING_HEADER_SIZE + pPath->u16Size); 367 pReq->CreateParms.Handle = SHFL_HANDLE_NIL; 368 pReq->CreateParms.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW; 369 370 rc = VbglR0SfHostReqCreate(sf_g->map.root, pReq); 371 if (RT_SUCCESS(rc)) { 372 if (pReq->CreateParms.Result == SHFL_FILE_EXISTS) { 373 /* 374 * Reset the TTL and copy the info over into the inode structure. 375 */ 376 sf_update_inode(pInode, sf_i, &pReq->CreateParms.Info, 377 sf_g, true /*fInodeLocked??*/); 378 rc = 0; 379 } else { 380 rc = -ENOENT; 381 } 382 } else if (rc == VERR_INVALID_NAME) { 383 rc = -ENOENT; /* this can happen for names like 'foo*' on a Windows host */ 384 } else { 385 LogFunc(("VbglR0SfHostReqCreate failed on %s: %Rrc\n", pPath->String.ach, rc)); 386 rc = -EPROTO; 387 } 388 VbglR0PhysHeapFree(pReq); 389 } 390 else 391 rc = -ENOMEM; 392 } 393 } 394 } else { 395 LogFunc(("no dentry(%p) or inode(%p)\n", dentry, pInode)); 396 rc = -EINVAL; 397 } 398 return rc; 399 399 } 400 400 … … 421 421 int sf_inode_revalidate_with_handle(struct dentry *dentry, SHFLHANDLE hHostFile, bool fForced, bool fInodeLocked) 422 422 { 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 423 int err; 424 struct inode *pInode = dentry ? dentry->d_inode : NULL; 425 if (!pInode) { 426 LogFunc(("no dentry(%p) or inode(%p)\n", dentry, pInode)); 427 err = -EINVAL; 428 } else { 429 struct sf_inode_info *sf_i = GET_INODE_INFO(pInode); 430 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(pInode->i_sb); 431 AssertReturn(sf_i, -EINVAL); 432 AssertReturn(sf_g, -EINVAL); 433 434 /* 435 * Can we get away without any action here? 436 */ 437 if ( !fForced 438 && !sf_i->force_restat 439 && jiffies - sf_i->ts_up_to_date < sf_g->ttl) 440 err = 0; 441 else { 442 /* 443 * No, we have to query the file info from the host. 444 */ 445 VBOXSFOBJINFOREQ *pReq = (VBOXSFOBJINFOREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq)); 446 if (pReq) { 447 RT_ZERO(*pReq); 448 err = VbglR0SfHostReqQueryObjInfo(sf_g->map.root, pReq, hHostFile); 449 if (RT_SUCCESS(err)) { 450 /* 451 * Reset the TTL and copy the info over into the inode structure. 452 */ 453 sf_update_inode(pInode, sf_i, &pReq->ObjInfo, sf_g, fInodeLocked); 454 } else { 455 LogFunc(("VbglR0SfHostReqQueryObjInfo failed on %#RX64: %Rrc\n", hHostFile, err)); 456 err = -RTErrConvertToErrno(err); 457 } 458 VbglR0PhysHeapFree(pReq); 459 } else 460 err = -ENOMEM; 461 } 462 } 463 return err; 464 464 } 465 465 … … 471 471 472 472 # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) 473 int sf_getattr(const struct path *path, struct kstat *kstat, u32 request_mask, 474 unsigned int flags) 473 int sf_getattr(const struct path *path, struct kstat *kstat, u32 request_mask, unsigned int flags) 475 474 # else 476 475 int sf_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *kstat) 477 476 # endif 478 477 { 479 478 int rc; 480 479 # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) 481 480 struct dentry *dentry = path->dentry; 482 481 # endif 483 482 484 483 # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) 485 484 SFLOGFLOW(("sf_getattr: dentry=%p request_mask=%#x flags=%#x\n", dentry, request_mask, flags)); 486 485 # else 487 486 SFLOGFLOW(("sf_getattr: dentry=%p\n", dentry)); 488 487 # endif 489 488 490 489 # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 490 /* 491 * With the introduction of statx() userland can control whether we 492 * update the inode information or not. 493 */ 494 switch (flags & AT_STATX_SYNC_TYPE) { 495 default: 496 rc = sf_inode_revalidate_worker(dentry, false /*fForced*/); 497 break; 498 499 case AT_STATX_FORCE_SYNC: 500 rc = sf_inode_revalidate_worker(dentry, true /*fForced*/); 501 break; 502 503 case AT_STATX_DONT_SYNC: 504 rc = 0; 505 break; 506 } 508 507 # else 509 508 rc = sf_inode_revalidate_worker(dentry, false /*fForced*/); 510 509 # endif 511 512 513 514 515 510 if (rc == 0) { 511 /* Do generic filling in of info. */ 512 generic_fillattr(dentry->d_inode, kstat); 513 514 /* Add birth time. */ 516 515 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) 517 518 519 520 521 522 523 524 #endif 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 516 if (dentry->d_inode) { 517 struct sf_inode_info *pInodeInfo = GET_INODE_INFO(dentry->d_inode); 518 if (pInodeInfo) { 519 sf_ftime_from_timespec(&kstat->btime, &pInodeInfo->BirthTime); 520 kstat->result_mask |= STATX_BTIME; 521 } 522 } 523 #endif 524 525 /* 526 * FsPerf shows the following numbers for sequential file access against 527 * a tmpfs folder on an AMD 1950X host running debian buster/sid: 528 * 529 * block size = r128600 ----- r128755 ----- 530 * reads reads writes 531 * 4096 KB = 2254 MB/s 4953 MB/s 3668 MB/s 532 * 2048 KB = 2368 MB/s 4908 MB/s 3541 MB/s 533 * 1024 KB = 2208 MB/s 4011 MB/s 3291 MB/s 534 * 512 KB = 1908 MB/s 3399 MB/s 2721 MB/s 535 * 256 KB = 1625 MB/s 2679 MB/s 2251 MB/s 536 * 128 KB = 1413 MB/s 1967 MB/s 1684 MB/s 537 * 64 KB = 1152 MB/s 1409 MB/s 1265 MB/s 538 * 32 KB = 726 MB/s 815 MB/s 783 MB/s 539 * 16 KB = 683 MB/s 475 MB/s 540 * 8 KB = 294 MB/s 286 MB/s 541 * 4 KB = 145 MB/s 156 MB/s 149 MB/s 542 * 543 */ 544 if (S_ISREG(kstat->mode)) 545 kstat->blksize = _1M; 546 else if (S_ISDIR(kstat->mode)) 547 /** @todo this may need more tuning after we rewrite the directory handling. */ 548 kstat->blksize = _16K; 549 } 550 return rc; 552 551 } 553 552 554 553 int sf_setattr(struct dentry *dentry, struct iattr *iattr) 555 554 { 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 555 struct vbsf_super_info *sf_g; 556 struct sf_inode_info *sf_i; 557 union SetAttrReqs 558 { 559 VBOXSFCREATEREQ Create; 560 VBOXSFOBJINFOREQ Info; 561 VBOXSFSETFILESIZEREQ SetSize; 562 VBOXSFCLOSEREQ Close; 563 } *pReq; 564 size_t cbReq; 565 SHFLCREATEPARMS *pCreateParms; 566 SHFLFSOBJINFO *pInfo; 567 SHFLHANDLE hHostFile; 568 int vrc; 569 int err = 0; 570 571 TRACE(); 572 573 sf_g = VBSF_GET_SUPER_INFO(dentry->d_inode->i_sb); 574 sf_i = GET_INODE_INFO(dentry->d_inode); 575 cbReq = RT_MAX(sizeof(pReq->Info), sizeof(pReq->Create) + SHFLSTRING_HEADER_SIZE + sf_i->path->u16Size); 576 pReq = (union SetAttrReqs *)VbglR0PhysHeapAlloc(cbReq); 577 if (!pReq) { 578 LogFunc(("Failed to allocate %#x byte request buffer!\n", cbReq)); 579 return -ENOMEM; 580 } 581 pCreateParms = &pReq->Create.CreateParms; 582 pInfo = &pReq->Info.ObjInfo; 583 584 RT_ZERO(*pCreateParms); 585 pCreateParms->Handle = SHFL_HANDLE_NIL; 586 pCreateParms->CreateFlags = SHFL_CF_ACT_OPEN_IF_EXISTS 587 | SHFL_CF_ACT_FAIL_IF_NEW 588 | SHFL_CF_ACCESS_ATTR_WRITE; 589 590 /* this is at least required for Posix hosts */ 591 if (iattr->ia_valid & ATTR_SIZE) 592 pCreateParms->CreateFlags |= SHFL_CF_ACCESS_WRITE; 593 594 memcpy(&pReq->Create.StrPath, sf_i->path, SHFLSTRING_HEADER_SIZE + sf_i->path->u16Size); 595 vrc = VbglR0SfHostReqCreate(sf_g->map.root, &pReq->Create); 596 if (RT_SUCCESS(vrc)) { 597 hHostFile = pCreateParms->Handle; 598 } else { 599 err = -RTErrConvertToErrno(vrc); 600 LogFunc(("VbglR0SfCreate(%s) failed vrc=%Rrc err=%d\n", sf_i->path->String.ach, vrc, err)); 601 goto fail2; 602 } 603 if (pCreateParms->Result != SHFL_FILE_EXISTS) { 604 LogFunc(("file %s does not exist\n", sf_i->path->String.utf8)); 605 err = -ENOENT; 606 goto fail1; 607 } 608 609 /* Setting the file size and setting the other attributes has to be 610 * handled separately, see implementation of vbsfSetFSInfo() in 611 * vbsf.cpp */ 612 if (iattr->ia_valid & (ATTR_MODE | ATTR_ATIME | ATTR_MTIME)) { 614 613 # define mode_set(r) ((iattr->ia_mode & (S_##r)) ? RTFS_UNIX_##r : 0) 615 614 616 RT_ZERO(*pInfo); 617 if (iattr->ia_valid & ATTR_MODE) { 618 pInfo->Attr.fMode = mode_set(IRUSR); 619 pInfo->Attr.fMode |= mode_set(IWUSR); 620 pInfo->Attr.fMode |= mode_set(IXUSR); 621 pInfo->Attr.fMode |= mode_set(IRGRP); 622 pInfo->Attr.fMode |= mode_set(IWGRP); 623 pInfo->Attr.fMode |= mode_set(IXGRP); 624 pInfo->Attr.fMode |= mode_set(IROTH); 625 pInfo->Attr.fMode |= mode_set(IWOTH); 626 pInfo->Attr.fMode |= mode_set(IXOTH); 627 628 if (iattr->ia_mode & S_IFDIR) 629 pInfo->Attr.fMode |= RTFS_TYPE_DIRECTORY; 630 else 631 pInfo->Attr.fMode |= RTFS_TYPE_FILE; 632 } 633 634 if (iattr->ia_valid & ATTR_ATIME) 635 sf_timespec_from_ftime(&pInfo->AccessTime, 636 &iattr->ia_atime); 637 if (iattr->ia_valid & ATTR_MTIME) 638 sf_timespec_from_ftime(&pInfo->ModificationTime, 639 &iattr->ia_mtime); 640 /* ignore ctime (inode change time) as it can't be set from userland anyway */ 641 642 vrc = VbglR0SfHostReqSetObjInfo(sf_g->map.root, &pReq->Info, hHostFile); 643 if (RT_FAILURE(vrc)) { 644 err = -RTErrConvertToErrno(vrc); 645 LogFunc(("VbglR0SfHostReqSetObjInfo(%s) failed vrc=%Rrc err=%d\n", sf_i->path->String.ach, vrc, err)); 646 goto fail1; 647 } 648 } 649 650 if (iattr->ia_valid & ATTR_SIZE) { 651 vrc = VbglR0SfHostReqSetFileSize(sf_g->map.root, &pReq->SetSize, hHostFile, iattr->ia_size); 652 /** @todo Implement fallback if host is < 6.0? */ 653 if (RT_FAILURE(vrc)) { 654 err = -RTErrConvertToErrno(vrc); 655 LogFunc(("VbglR0SfHostReqSetFileSize(%s, %#llx) failed vrc=%Rrc err=%d\n", 656 sf_i->path->String.ach, (unsigned long long)iattr->ia_size, vrc, err)); 657 goto fail1; 658 } 659 } 660 661 vrc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, hHostFile); 662 if (RT_FAILURE(vrc)) 663 LogFunc(("VbglR0SfHostReqClose(%s [%#llx]) failed vrc=%Rrc\n", sf_i->path->String.utf8, hHostFile, vrc)); 664 VbglR0PhysHeapFree(pReq); 665 666 /** @todo r=bird: I guess we're calling revalidate here to update the inode 667 * info. However, due to the TTL optimization this is not guarenteed to happen. 668 * 669 * Also, we already have accurate stat information on the file, either from the 670 * SHFL_FN_CREATE call or from SHFL_FN_INFORMATION, so there is no need to do a 671 * slow stat()-like operation to retrieve the information again. 672 * 673 * What's more, given that the SHFL_FN_CREATE call succeeded, we know that the 674 * dentry and all its parent entries are valid and could touch their timestamps 675 * extending their TTL (CIFS does that). */ 676 return sf_inode_revalidate_worker(dentry, true /*fForced*/); 615 RT_ZERO(*pInfo); 616 if (iattr->ia_valid & ATTR_MODE) { 617 /** @todo we've got code for this elsewhere... */ 618 pInfo->Attr.fMode = mode_set(IRUSR); 619 pInfo->Attr.fMode |= mode_set(IWUSR); 620 pInfo->Attr.fMode |= mode_set(IXUSR); 621 pInfo->Attr.fMode |= mode_set(IRGRP); 622 pInfo->Attr.fMode |= mode_set(IWGRP); 623 pInfo->Attr.fMode |= mode_set(IXGRP); 624 pInfo->Attr.fMode |= mode_set(IROTH); 625 pInfo->Attr.fMode |= mode_set(IWOTH); 626 pInfo->Attr.fMode |= mode_set(IXOTH); 627 628 if (iattr->ia_mode & S_IFDIR) 629 pInfo->Attr.fMode |= RTFS_TYPE_DIRECTORY; 630 else 631 pInfo->Attr.fMode |= RTFS_TYPE_FILE; 632 } 633 634 if (iattr->ia_valid & ATTR_ATIME) 635 sf_timespec_from_ftime(&pInfo->AccessTime, &iattr->ia_atime); 636 if (iattr->ia_valid & ATTR_MTIME) 637 sf_timespec_from_ftime(&pInfo->ModificationTime, &iattr->ia_mtime); 638 /* ignore ctime (inode change time) as it can't be set from userland anyway */ 639 640 vrc = VbglR0SfHostReqSetObjInfo(sf_g->map.root, &pReq->Info, hHostFile); 641 if (RT_FAILURE(vrc)) { 642 err = -RTErrConvertToErrno(vrc); 643 LogFunc(("VbglR0SfHostReqSetObjInfo(%s) failed vrc=%Rrc err=%d\n", sf_i->path->String.ach, vrc, err)); 644 goto fail1; 645 } 646 } 647 648 if (iattr->ia_valid & ATTR_SIZE) { 649 vrc = VbglR0SfHostReqSetFileSize(sf_g->map.root, &pReq->SetSize, hHostFile, iattr->ia_size); 650 /** @todo Implement fallback if host is < 6.0? */ 651 if (RT_FAILURE(vrc)) { 652 err = -RTErrConvertToErrno(vrc); 653 LogFunc(("VbglR0SfHostReqSetFileSize(%s, %#llx) failed vrc=%Rrc err=%d\n", 654 sf_i->path->String.ach, (unsigned long long)iattr->ia_size, vrc, err)); 655 goto fail1; 656 } 657 } 658 659 vrc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, hHostFile); 660 if (RT_FAILURE(vrc)) 661 LogFunc(("VbglR0SfHostReqClose(%s [%#llx]) failed vrc=%Rrc\n", sf_i->path->String.utf8, hHostFile, vrc)); 662 VbglR0PhysHeapFree(pReq); 663 664 /** @todo r=bird: I guess we're calling revalidate here to update the inode 665 * info. However, due to the TTL optimization this is not guarenteed to happen. 666 * 667 * Also, we already have accurate stat information on the file, either from the 668 * SHFL_FN_CREATE call or from SHFL_FN_INFORMATION, so there is no need to do a 669 * slow stat()-like operation to retrieve the information again. 670 * 671 * What's more, given that the SHFL_FN_CREATE call succeeded, we know that the 672 * dentry and all its parent entries are valid and could touch their timestamps 673 * extending their TTL (CIFS does that). */ 674 return sf_inode_revalidate_worker(dentry, true /*fForced*/); 677 675 678 676 fail1: 679 680 681 677 vrc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, hHostFile); 678 if (RT_FAILURE(vrc)) 679 LogFunc(("VbglR0SfHostReqClose(%s [%#llx]) failed vrc=%Rrc; err=%d\n", sf_i->path->String.utf8, hHostFile, vrc, err)); 682 680 683 681 fail2: 684 685 682 VbglR0PhysHeapFree(pReq); 683 return err; 686 684 } 687 685 … … 689 687 690 688 static int sf_make_path(const char *caller, struct sf_inode_info *sf_i, 691 const char *d_name, size_t d_len, SHFLSTRING **result)692 { 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 689 const char *d_name, size_t d_len, SHFLSTRING **result) 690 { 691 size_t path_len, shflstring_len; 692 SHFLSTRING *tmp; 693 uint16_t p_len; 694 uint8_t *p_name; 695 int fRoot = 0; 696 697 TRACE(); 698 p_len = sf_i->path->u16Length; 699 p_name = sf_i->path->String.utf8; 700 701 if (p_len == 1 && *p_name == '/') { 702 path_len = d_len + 1; 703 fRoot = 1; 704 } else { 705 /* lengths of constituents plus terminating zero plus slash */ 706 path_len = p_len + d_len + 2; 707 if (path_len > 0xffff) { 708 LogFunc(("path too long. caller=%s, path_len=%zu\n", 709 caller, path_len)); 710 return -ENAMETOOLONG; 711 } 712 } 713 714 shflstring_len = offsetof(SHFLSTRING, String.utf8) + path_len; 715 tmp = kmalloc(shflstring_len, GFP_KERNEL); 716 if (!tmp) { 717 LogRelFunc(("kmalloc failed, caller=%s\n", caller)); 718 return -ENOMEM; 719 } 720 tmp->u16Length = path_len - 1; 721 tmp->u16Size = path_len; 722 723 if (fRoot) 724 memcpy(&tmp->String.utf8[0], d_name, d_len + 1); 725 else { 726 memcpy(&tmp->String.utf8[0], p_name, p_len); 727 tmp->String.utf8[p_len] = '/'; 728 memcpy(&tmp->String.utf8[p_len + 1], d_name, d_len); 729 tmp->String.utf8[p_len + 1 + d_len] = '\0'; 730 } 731 732 *result = tmp; 733 return 0; 736 734 } 737 735 … … 742 740 */ 743 741 int sf_path_from_dentry(const char *caller, struct vbsf_super_info *sf_g, 744 745 SHFLSTRING **result)746 { 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 742 struct sf_inode_info *sf_i, struct dentry *dentry, 743 SHFLSTRING **result) 744 { 745 int err; 746 const char *d_name; 747 size_t d_len; 748 const char *name; 749 size_t len = 0; 750 751 TRACE(); 752 d_name = dentry->d_name.name; 753 d_len = dentry->d_name.len; 754 755 if (sf_g->nls) { 756 size_t in_len, i, out_bound_len; 757 const char *in; 758 char *out; 759 760 in = d_name; 761 in_len = d_len; 762 763 out_bound_len = PATH_MAX; 764 out = kmalloc(out_bound_len, GFP_KERNEL); 765 name = out; 766 767 for (i = 0; i < d_len; ++i) { 768 /* We renamed the linux kernel wchar_t type to linux_wchar_t in 769 the-linux-kernel.h, as it conflicts with the C++ type of that name. */ 770 linux_wchar_t uni; 771 int nb; 772 773 nb = sf_g->nls->char2uni(in, in_len, &uni); 774 if (nb < 0) { 775 LogFunc(("nls->char2uni failed %x %d\n", 776 *in, in_len)); 777 err = -EINVAL; 778 goto fail1; 779 } 780 in_len -= nb; 781 in += nb; 784 782 785 783 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) 786 784 nb = utf32_to_utf8(uni, out, out_bound_len); 787 785 #else 788 789 #endif 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 786 nb = utf8_wctomb(out, uni, out_bound_len); 787 #endif 788 if (nb < 0) { 789 LogFunc(("nls->uni2char failed %x %d\n", 790 uni, out_bound_len)); 791 err = -EINVAL; 792 goto fail1; 793 } 794 out_bound_len -= nb; 795 out += nb; 796 len += nb; 797 } 798 if (len >= PATH_MAX - 1) { 799 err = -ENAMETOOLONG; 800 goto fail1; 801 } 802 803 LogFunc(("result(%d) = %.*s\n", len, len, name)); 804 *out = 0; 805 } else { 806 name = d_name; 807 len = d_len; 808 } 809 810 err = sf_make_path(caller, sf_i, name, len, result); 811 if (name != d_name) 812 kfree(name); 813 814 return err; 817 815 818 816 fail1: 819 820 817 kfree(name); 818 return err; 821 819 } 822 820 823 821 int sf_nlscpy(struct vbsf_super_info *sf_g, 824 825 826 { 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 822 char *name, size_t name_bound_len, 823 const unsigned char *utf8_name, size_t utf8_len) 824 { 825 if (sf_g->nls) { 826 const char *in; 827 char *out; 828 size_t out_len; 829 size_t out_bound_len; 830 size_t in_bound_len; 831 832 in = utf8_name; 833 in_bound_len = utf8_len; 834 835 out = name; 836 out_len = 0; 837 out_bound_len = name_bound_len; 838 839 while (in_bound_len) { 840 int nb; 843 841 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) 844 845 846 842 unicode_t uni; 843 844 nb = utf8_to_utf32(in, in_bound_len, &uni); 847 845 #else 848 849 850 851 #endif 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 846 linux_wchar_t uni; 847 848 nb = utf8_mbtowc(&uni, in, in_bound_len); 849 #endif 850 if (nb < 0) { 851 LogFunc(("utf8_mbtowc failed(%s) %x:%d\n", 852 (const char *)utf8_name, *in, 853 in_bound_len)); 854 return -EINVAL; 855 } 856 in += nb; 857 in_bound_len -= nb; 858 859 nb = sf_g->nls->uni2char(uni, out, out_bound_len); 860 if (nb < 0) { 861 LogFunc(("nls->uni2char failed(%s) %x:%d\n", 862 utf8_name, uni, out_bound_len)); 863 return nb; 864 } 865 out += nb; 866 out_bound_len -= nb; 867 out_len += nb; 868 } 869 870 *out = 0; 871 } else { 872 if (utf8_len + 1 > name_bound_len) 873 return -ENAMETOOLONG; 874 875 memcpy(name, utf8_name, utf8_len + 1); 876 } 877 return 0; 880 878 } 881 879 882 880 static struct sf_dir_buf *sf_dir_buf_alloc(void) 883 881 { 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 882 struct sf_dir_buf *b; 883 884 TRACE(); 885 b = kmalloc(sizeof(*b), GFP_KERNEL); 886 if (!b) { 887 LogRelFunc(("could not alloc directory buffer\n")); 888 return NULL; 889 } 890 b->buf = kmalloc(DIR_BUFFER_SIZE, GFP_KERNEL); 891 if (!b->buf) { 892 kfree(b); 893 LogRelFunc(("could not alloc directory buffer storage\n")); 894 return NULL; 895 } 896 897 INIT_LIST_HEAD(&b->head); 898 b->cEntries = 0; 899 b->cbUsed = 0; 900 b->cbFree = DIR_BUFFER_SIZE; 901 return b; 904 902 } 905 903 906 904 static void sf_dir_buf_free(struct sf_dir_buf *b) 907 905 { 908 909 910 911 912 913 906 BUG_ON(!b || !b->buf); 907 908 TRACE(); 909 list_del(&b->head); 910 kfree(b->buf); 911 kfree(b); 914 912 } 915 913 … … 919 917 void sf_dir_info_free(struct sf_dir_info *p) 920 918 { 921 922 923 924 925 926 927 928 929 930 931 919 struct list_head *list, *pos, *tmp; 920 921 TRACE(); 922 list = &p->info_list; 923 list_for_each_safe(pos, tmp, list) { 924 struct sf_dir_buf *b; 925 926 b = list_entry(pos, struct sf_dir_buf, head); 927 sf_dir_buf_free(b); 928 } 929 kfree(p); 932 930 } 933 931 … … 937 935 void sf_dir_info_empty(struct sf_dir_info *p) 938 936 { 939 940 941 942 943 944 945 946 947 948 937 struct list_head *list, *pos, *tmp; 938 TRACE(); 939 list = &p->info_list; 940 list_for_each_safe(pos, tmp, list) { 941 struct sf_dir_buf *b; 942 b = list_entry(pos, struct sf_dir_buf, head); 943 b->cEntries = 0; 944 b->cbUsed = 0; 945 b->cbFree = DIR_BUFFER_SIZE; 946 } 949 947 } 950 948 … … 954 952 struct sf_dir_info *sf_dir_info_alloc(void) 955 953 { 956 957 958 959 960 961 962 963 964 965 966 954 struct sf_dir_info *p; 955 956 TRACE(); 957 p = kmalloc(sizeof(*p), GFP_KERNEL); 958 if (!p) { 959 LogRelFunc(("could not alloc directory info\n")); 960 return NULL; 961 } 962 963 INIT_LIST_HEAD(&p->info_list); 964 return p; 967 965 } 968 966 … … 972 970 static struct sf_dir_buf *sf_get_empty_dir_buf(struct sf_dir_info *sf_d) 973 971 { 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 972 struct list_head *list, *pos; 973 974 list = &sf_d->info_list; 975 list_for_each(pos, list) { 976 struct sf_dir_buf *b; 977 978 b = list_entry(pos, struct sf_dir_buf, head); 979 if (!b) 980 return NULL; 981 else { 982 if (b->cbUsed == 0) 983 return b; 984 } 985 } 986 987 return NULL; 990 988 } 991 989 … … 993 991 * cannot be healthy for like big directory and such... */ 994 992 int sf_dir_read_all(struct vbsf_super_info *sf_g, struct sf_inode_info *sf_i, 995 996 { 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 993 struct sf_dir_info *sf_d, SHFLHANDLE handle) 994 { 995 int err; 996 SHFLSTRING *mask; 997 VBOXSFLISTDIRREQ *pReq = NULL; 998 999 TRACE(); 1000 err = sf_make_path(__func__, sf_i, "*", 1, &mask); 1001 if (err) 1002 goto fail0; 1003 pReq = (VBOXSFLISTDIRREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq)); 1004 if (!pReq) 1005 goto fail1; 1006 1007 for (;;) { 1008 int rc; 1009 struct sf_dir_buf *b; 1010 1011 b = sf_get_empty_dir_buf(sf_d); 1012 if (!b) { 1013 b = sf_dir_buf_alloc(); 1014 if (!b) { 1015 err = -ENOMEM; 1016 LogRelFunc(("could not alloc directory buffer\n")); 1017 goto fail2; 1018 } 1019 list_add(&b->head, &sf_d->info_list); 1020 } 1021 1022 rc = VbglR0SfHostReqListDirContig2x(sf_g->map.root, pReq, handle, mask, virt_to_phys(mask), 1023 0 /*fFlags*/, b->buf, virt_to_phys(b->buf), b->cbFree); 1024 if (RT_SUCCESS(rc)) { 1025 b->cEntries += pReq->Parms.c32Entries.u.value32; 1026 b->cbFree -= pReq->Parms.cb32Buffer.u.value32; 1027 b->cbUsed += pReq->Parms.cb32Buffer.u.value32; 1028 } else if (rc == VERR_NO_MORE_FILES) { 1029 break; 1030 } else { 1031 err = -RTErrConvertToErrno(rc); 1032 LogFunc(("VbglR0SfHostReqListDirContig2x failed rc=%Rrc err=%d\n", rc, err)); 1033 goto fail2; 1034 } 1035 } 1036 err = 0; 1039 1037 1040 1038 fail2: 1041 1039 VbglR0PhysHeapFree(pReq); 1042 1040 fail1: 1043 1041 kfree(mask); 1044 1042 1045 1043 fail0: 1046 1044 return err; 1047 1045 } 1048 1046 … … 1063 1061 { 1064 1062 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) 1065 1066 #endif 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 *https://lwn.net/Articles/649729/1078 *https://lwn.net/Articles/650786/1079 1080 1063 int const flags = nd ? nd->flags : 0; 1064 #endif 1065 1066 int rc; 1067 1068 Assert(dentry); 1069 SFLOGFLOW(("sf_dentry_revalidate: %p %#x %s\n", dentry, flags, dentry->d_inode ? GET_INODE_INFO(dentry->d_inode)->path->String.ach : "<negative>")); 1070 1071 /* 1072 * See Documentation/filesystems/vfs.txt why we skip LOOKUP_RCU. 1073 * 1074 * Also recommended: https://lwn.net/Articles/649115/ 1075 * https://lwn.net/Articles/649729/ 1076 * https://lwn.net/Articles/650786/ 1077 * 1078 */ 1081 1079 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38) 1082 1083 1084 1085 1086 #endif 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1080 if (flags & LOOKUP_RCU) { 1081 rc = -ECHILD; 1082 SFLOGFLOW(("sf_dentry_revalidate: RCU -> -ECHILD\n")); 1083 } else 1084 #endif 1085 { 1086 /* 1087 * Do we have an inode or not? If not it's probably a negative cache 1088 * entry, otherwise most likely a positive one. 1089 */ 1090 struct inode *pInode = dentry->d_inode; 1091 if (pInode) { 1092 /* 1093 * Positive entry. 1094 * 1095 * Note! We're more aggressive here than other remote file systems, 1096 * current (4.19) CIFS will for instance revalidate the inode 1097 * and ignore the dentry timestamp for positive entries. 1098 */ 1099 //struct sf_inode_info *sf_i = GET_INODE_INFO(pInode); 1100 unsigned long const cJiffiesAge = sf_dentry_get_update_jiffies(dentry) - jiffies; 1101 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(dentry->d_sb); 1102 if (cJiffiesAge < sf_g->ttl) { 1103 SFLOGFLOW(("sf_dentry_revalidate: age: %lu vs. TTL %lu -> 1\n", cJiffiesAge, sf_g->ttl)); 1104 rc = 1; 1105 } else if (!sf_inode_revalidate_worker(dentry, true /*fForced*/)) { 1106 sf_dentry_set_update_jiffies(dentry, jiffies); /** @todo get jiffies from inode. */ 1107 SFLOGFLOW(("sf_dentry_revalidate: age: %lu vs. TTL %lu -> reval -> 1\n", cJiffiesAge, sf_g->ttl)); 1108 rc = 1; 1109 } else { 1110 SFLOGFLOW(("sf_dentry_revalidate: age: %lu vs. TTL %lu -> reval -> 0\n", cJiffiesAge, sf_g->ttl)); 1111 rc = 0; 1112 } 1113 } else { 1114 /* 1115 * Negative entry. 1116 * 1117 * Invalidate dentries for open and renames here as we'll revalidate 1118 * these when taking the actual action (also good for case preservation 1119 * if we do case-insensitive mounts against windows + mac hosts at some 1120 * later point). 1121 */ 1124 1122 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 1125 1123 if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) 1126 1124 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 75) 1127 1125 if (flags & LOOKUP_CREATE) 1128 1126 #else 1129 1130 #endif 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1127 if (0) 1128 #endif 1129 { 1130 SFLOGFLOW(("sf_dentry_revalidate: negative: create or rename target -> 0\n")); 1131 rc = 0; 1132 } else { 1133 /* Can we skip revalidation based on TTL? */ 1134 unsigned long const cJiffiesAge = sf_dentry_get_update_jiffies(dentry) - jiffies; 1135 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(dentry->d_sb); 1136 if (cJiffiesAge < sf_g->ttl) { 1137 SFLOGFLOW(("sf_dentry_revalidate: negative: age: %lu vs. TTL %lu -> 1\n", cJiffiesAge, sf_g->ttl)); 1138 rc = 1; 1139 } else { 1140 /* We could revalidate it here, but we could instead just 1141 have the caller kick it out. */ 1142 /** @todo stat the direntry and see if it exists now. */ 1143 SFLOGFLOW(("sf_dentry_revalidate: negative: age: %lu vs. TTL %lu -> 0\n", cJiffiesAge, sf_g->ttl)); 1144 rc = 0; 1145 } 1146 } 1147 } 1148 } 1149 return rc; 1152 1150 } 1153 1151 … … 1161 1159 # endif 1162 1160 { 1163 1164 1161 SFLOGFLOW(("sf_dentry_delete: %p\n", pDirEntry)); 1162 return 0; 1165 1163 } 1166 1164 … … 1169 1167 static int sf_dentry_init(struct dentry *pDirEntry) 1170 1168 { 1171 1172 1169 SFLOGFLOW(("sf_dentry_init: %p\n", pDirEntry)); 1170 return 0; 1173 1171 } 1174 1172 # endif … … 1182 1180 */ 1183 1181 struct dentry_operations sf_dentry_ops = { 1184 1182 .d_revalidate = sf_dentry_revalidate, 1185 1183 #ifdef SFLOG_ENABLED 1186 1184 .d_delete = sf_dentry_delete, 1187 1185 # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) 1188 1186 .d_init = sf_dentry_init, 1189 1187 # endif 1190 1188 #endif -
trunk/src/VBox/Additions/linux/sharedfolders/vbsfmount.h
r77492 r77526 45 45 46 46 struct vbsf_mount_info_new { 47 48 49 50 51 52 53 54 55 char signature[3];/**< signature */56 int length;/**< length of the whole structure */57 char name[MAX_HOST_NAME];/**< share name */58 char nls_name[MAX_NLS_NAME];/**< name of an I/O charset */59 int uid;/**< user ID for all entries, default 0=root */60 int gid;/**< group ID for all entries, default 0=root */61 int ttl;/**< directory entry and inode time to live in milliseconds.62 63 int dmode;/**< mode for directories if != 0xffffffff */64 int fmode;/**< mode for regular files if != 0xffffffff */65 int dmask;/**< umask applied to directories */66 int fmask;/**< umask applied to regular files */67 char tag[32];/**< Mount tag for VBoxService automounter. @since 6.0 */68 uint32_t cMaxIoPages;/**< Max pages to read & write at a time. @since 6.0.6 */47 /** 48 * The old version of the mount_info struct started with a 49 * char name[MAX_HOST_NAME] field, where name cannot be '\0'. 50 * So the new version of the mount_info struct starts with a 51 * nullchar field which is always 0 so that we can detect and 52 * reject the old structure being passed. 53 */ 54 char nullchar; 55 char signature[3]; /**< signature */ 56 int length; /**< length of the whole structure */ 57 char name[MAX_HOST_NAME]; /**< share name */ 58 char nls_name[MAX_NLS_NAME];/**< name of an I/O charset */ 59 int uid; /**< user ID for all entries, default 0=root */ 60 int gid; /**< group ID for all entries, default 0=root */ 61 int ttl; /**< directory entry and inode time to live in milliseconds. 62 * -1 for kernel default, 0 to disable caching. */ 63 int dmode; /**< mode for directories if != 0xffffffff */ 64 int fmode; /**< mode for regular files if != 0xffffffff */ 65 int dmask; /**< umask applied to directories */ 66 int fmask; /**< umask applied to regular files */ 67 char tag[32]; /**< Mount tag for VBoxService automounter. @since 6.0 */ 68 uint32_t cMaxIoPages; /**< Max pages to read & write at a time. @since 6.0.6 */ 69 69 }; 70 70 71 71 struct vbsf_mount_opts { 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 72 int uid; 73 int gid; 74 int ttl; 75 int dmode; 76 int fmode; 77 int dmask; 78 int fmask; 79 int ronly; 80 int sloppy; 81 int noexec; 82 int nodev; 83 int nosuid; 84 int remount; 85 char nls_name[MAX_NLS_NAME]; 86 char *convertcp; 87 uint32_t cMaxIoPages; 88 88 }; 89 89 90 90 /** Completes the mount operation by adding the new mount point to mtab if required. */ 91 91 int vbsfmount_complete(const char *host_name, const char *mount_point, 92 92 unsigned long flags, struct vbsf_mount_opts *opts); 93 93 94 94 #endif /* !GA_INCLUDED_SRC_linux_sharedfolders_vbsfmount_h */ -
trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.c
r77524 r77526 37 37 * See also: http://us1.samba.org/samba/ftp/cifs-cvs/ols2006-fs-tutorial-smf.odp 38 38 */ 39 39 40 40 41 /********************************************************************************************************************************* … … 81 82 static void sf_super_info_copy_remount_options(struct vbsf_super_info *sf_g, struct vbsf_mount_info_new *info) 82 83 { 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 84 sf_g->ttl_msec = info->ttl; 85 if (info->ttl > 0) 86 sf_g->ttl = msecs_to_jiffies(info->ttl); 87 else if (info->ttl == 0 || info->ttl != -1) 88 sf_g->ttl = sf_g->ttl_msec = 0; 89 else 90 sf_g->ttl = msecs_to_jiffies(VBSF_DEFAULT_TTL_MS); 91 92 sf_g->uid = info->uid; 93 sf_g->gid = info->gid; 94 95 if ((unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, tag)) { 96 /* new fields */ 97 sf_g->dmode = info->dmode; 98 sf_g->fmode = info->fmode; 99 sf_g->dmask = info->dmask; 100 sf_g->fmask = info->fmask; 101 } else { 102 sf_g->dmode = ~0; 103 sf_g->fmode = ~0; 104 } 105 106 if ((unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, cMaxIoPages)) { 107 AssertCompile(sizeof(sf_g->tag) >= sizeof(info->tag)); 108 memcpy(sf_g->tag, info->tag, sizeof(info->tag)); 109 sf_g->tag[sizeof(sf_g->tag) - 1] = '\0'; 110 } else { 111 sf_g->tag[0] = '\0'; 112 } 113 114 /* The max number of pages in an I/O request. This must take into 115 account that the physical heap generally grows in 64 KB chunks, 116 so we should not try push that limit. It also needs to take 117 into account that the host will allocate temporary heap buffers 118 for the I/O bytes we send/receive, so don't push the host heap 119 too hard as we'd have to retry with smaller requests when this 120 happens, which isn't too efficient. */ 121 sf_g->cMaxIoPages = RT_MIN(_16K / sizeof(RTGCPHYS64) /* => 8MB buffer */, 122 VMMDEV_MAX_HGCM_DATA_SIZE >> PAGE_SHIFT); 123 if ( (unsigned)info->length >= sizeof(struct vbsf_mount_info_new) 124 && info->cMaxIoPages != 0) { 125 if (info->cMaxIoPages <= VMMDEV_MAX_HGCM_DATA_SIZE >> PAGE_SHIFT) 126 sf_g->cMaxIoPages = info->cMaxIoPages; 127 else 128 printk(KERN_WARNING "vboxsf: max I/O page count (%#x) is out of range, using default (%#x) instead.\n", 129 info->cMaxIoPages, sf_g->cMaxIoPages); 130 } 130 131 } 131 132 … … 133 134 static int sf_super_info_alloc(struct vbsf_mount_info_new *info, struct vbsf_super_info **sf_gp) 134 135 { 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 136 int err, rc; 137 SHFLSTRING *str_name; 138 size_t name_len, str_len; 139 struct vbsf_super_info *sf_g; 140 141 TRACE(); 142 sf_g = kmalloc(sizeof(*sf_g), GFP_KERNEL); 143 if (!sf_g) { 144 err = -ENOMEM; 145 LogRelFunc(("could not allocate memory for super info\n")); 146 goto fail0; 147 } 148 149 RT_ZERO(*sf_g); 150 151 if (info->nullchar != '\0' 152 || info->signature[0] != VBSF_MOUNT_SIGNATURE_BYTE_0 153 || info->signature[1] != VBSF_MOUNT_SIGNATURE_BYTE_1 154 || info->signature[2] != VBSF_MOUNT_SIGNATURE_BYTE_2) { 155 err = -EINVAL; 156 goto fail1; 157 } 158 159 info->name[sizeof(info->name) - 1] = 0; 160 info->nls_name[sizeof(info->nls_name) - 1] = 0; 161 162 name_len = strlen(info->name); 163 str_len = offsetof(SHFLSTRING, String.utf8) + name_len + 1; 164 str_name = kmalloc(str_len, GFP_KERNEL); 165 if (!str_name) { 166 err = -ENOMEM; 167 LogRelFunc(("could not allocate memory for host name\n")); 168 goto fail1; 169 } 170 171 str_name->u16Length = name_len; 172 str_name->u16Size = name_len + 1; 173 memcpy(str_name->String.utf8, info->name, name_len + 1); 173 174 174 175 #define _IS_UTF8(_str) (strcmp(_str, "utf8") == 0) 175 176 #define _IS_EMPTY(_str) (strcmp(_str, "") == 0) 176 177 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 178 /* Check if NLS charset is valid and not points to UTF8 table */ 179 if (info->nls_name[0]) { 180 if (_IS_UTF8(info->nls_name)) 181 sf_g->nls = NULL; 182 else { 183 sf_g->nls = load_nls(info->nls_name); 184 if (!sf_g->nls) { 185 err = -EINVAL; 186 LogFunc(("failed to load nls %s\n", 187 info->nls_name)); 188 kfree(str_name); 189 goto fail1; 190 } 191 } 192 } else { 192 193 #ifdef CONFIG_NLS_DEFAULT 193 194 195 196 197 198 199 194 /* If no NLS charset specified, try to load the default 195 * one if it's not points to UTF8. */ 196 if (!_IS_UTF8(CONFIG_NLS_DEFAULT) 197 && !_IS_EMPTY(CONFIG_NLS_DEFAULT)) 198 sf_g->nls = load_nls_default(); 199 else 200 sf_g->nls = NULL; 200 201 #else 201 202 #endif 203 202 sf_g->nls = NULL; 203 #endif 204 } 204 205 205 206 #undef _IS_UTF8 206 207 #undef _IS_EMPTY 207 208 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 209 rc = VbglR0SfHostReqMapFolderWithContigSimple(str_name, virt_to_phys(str_name), RTPATH_DELIMITER, 210 true /*fCaseSensitive*/, &sf_g->map.root); 211 kfree(str_name); 212 213 if (RT_FAILURE(rc)) { 214 err = -EPROTO; 215 LogFunc(("SHFL_FN_MAP_FOLDER failed rc=%Rrc\n", rc)); 216 goto fail2; 217 } 218 219 /* The rest is shared with remount. */ 220 sf_super_info_copy_remount_options(sf_g, info); 221 222 *sf_gp = sf_g; 223 return 0; 223 224 224 225 fail2: 225 226 226 if (sf_g->nls) 227 unload_nls(sf_g->nls); 227 228 228 229 fail1: 229 230 kfree(sf_g); 230 231 231 232 fail0: 232 233 return err; 233 234 } 234 235 … … 236 237 static void sf_super_info_free(struct vbsf_super_info *sf_g) 237 238 { 238 239 240 241 242 243 244 245 246 247 248 239 int rc; 240 241 TRACE(); 242 rc = VbglR0SfHostReqUnmapFolderSimple(sf_g->map.root); 243 if (RT_FAILURE(rc)) 244 LogFunc(("VbglR0SfHostReqUnmapFolderSimple failed rc=%Rrc\n", rc)); 245 246 if (sf_g->nls) 247 unload_nls(sf_g->nls); 248 249 kfree(sf_g); 249 250 } 250 251 … … 255 256 static int sf_init_backing_dev(struct super_block *sb, struct vbsf_super_info *sf_g) 256 257 { 257 258 int rc = 0; 258 259 /** @todo this needs sorting out between 3.19 and 4.11 */ 259 260 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) //&& LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19, 0) 260 261 261 /* Each new shared folder map gets a new uint64_t identifier, 262 * allocated in sequence. We ASSUME the sequence will not wrap. */ 262 263 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) 263 264 265 #endif 266 264 static uint64_t s_u64Sequence = 0; 265 uint64_t u64CurrentSequence = ASMAtomicIncU64(&s_u64Sequence); 266 #endif 267 struct backing_dev_info *bdi; 267 268 268 269 # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) 269 270 271 272 273 270 rc = super_setup_bdi_name(sb, "vboxsf-%llu", (unsigned long long)u64CurrentSequence); 271 if (!rc) 272 bdi = sb->s_bdi; 273 else 274 return rc; 274 275 # else 275 276 bdi = &sf_g->bdi; 276 277 # endif 277 278 278 279 bdi->ra_pages = 0; /* No readahead */ 279 280 280 281 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12) 281 282 bdi->capabilities = 0 282 283 # ifdef BDI_CAP_MAP_DIRECT 283 284 | BDI_CAP_MAP_DIRECT /* MAP_SHARED */ 284 285 # endif 285 286 # ifdef BDI_CAP_MAP_COPY 286 287 | BDI_CAP_MAP_COPY /* MAP_PRIVATE */ 287 288 # endif 288 289 # ifdef BDI_CAP_READ_MAP 289 290 | BDI_CAP_READ_MAP /* can be mapped for reading */ 290 291 # endif 291 292 # ifdef BDI_CAP_WRITE_MAP 292 293 | BDI_CAP_WRITE_MAP /* can be mapped for writing */ 293 294 # endif 294 295 # ifdef BDI_CAP_EXEC_MAP 295 296 | BDI_CAP_EXEC_MAP /* can be mapped for execution */ 296 297 # endif 297 298 # ifdef BDI_CAP_STRICTLIMIT 298 299 | BDI_CAP_STRICTLIMIT; 299 300 # endif 300 301 ; 301 302 # ifdef BDI_CAP_STRICTLIMIT 302 303 303 /* Smalles possible amount of dirty pages: %1 of RAM */ 304 bdi_set_max_ratio(bdi, 1); 304 305 # endif 305 # endif 306 # endif /* >= 2.6.12 */ 306 307 307 308 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) 308 309 rc = bdi_init(&sf_g->bdi); 309 310 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) 310 311 312 311 if (!rc) 312 rc = bdi_register(&sf_g->bdi, NULL, "vboxsf-%llu", 313 (unsigned long long)u64CurrentSequence); 313 314 # endif /* >= 2.6.26 */ 314 # endif 315 # endif /* >= 2.6.24 */ 315 316 #endif /* >= 2.6.0 */ 316 317 return rc; 317 318 } 318 319 … … 324 325 { 325 326 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19, 0) 326 bdi_destroy(&sf_g->bdi);/* includes bdi_unregister() */327 bdi_destroy(&sf_g->bdi); /* includes bdi_unregister() */ 327 328 #endif 328 329 } … … 342 343 static int sf_read_super_aux(struct super_block *sb, void *data, int flags) 343 344 { 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 345 int err; 346 struct dentry *droot; 347 struct inode *iroot; 348 struct sf_inode_info *sf_i; 349 struct vbsf_super_info *sf_g; 350 SHFLFSOBJINFO fsinfo; 351 struct vbsf_mount_info_new *info; 352 bool fInodePut = true; 353 354 TRACE(); 355 if (!data) { 356 LogFunc(("no mount info specified\n")); 357 return -EINVAL; 358 } 359 360 info = data; 361 362 if (flags & MS_REMOUNT) { 363 LogFunc(("remounting is not supported\n")); 364 return -ENOSYS; 365 } 366 367 err = sf_super_info_alloc(info, &sf_g); 368 if (err) 369 goto fail0; 370 371 sf_i = kmalloc(sizeof(*sf_i), GFP_KERNEL); 372 if (!sf_i) { 373 err = -ENOMEM; 374 LogRelFunc(("could not allocate memory for root inode info\n")); 375 goto fail1; 376 } 377 378 sf_i->handle = SHFL_HANDLE_NIL; 379 sf_i->path = kmalloc(sizeof(SHFLSTRING) + 1, GFP_KERNEL); 380 if (!sf_i->path) { 381 err = -ENOMEM; 382 LogRelFunc(("could not allocate memory for root inode path\n")); 383 goto fail2; 384 } 385 386 sf_i->path->u16Length = 1; 387 sf_i->path->u16Size = 2; 388 sf_i->path->String.utf8[0] = '/'; 389 sf_i->path->String.utf8[1] = 0; 390 sf_i->force_reread = 0; 391 RTListInit(&sf_i->HandleList); 391 392 #ifdef VBOX_STRICT 392 393 #endif 394 395 396 397 398 399 400 401 402 393 sf_i->u32Magic = SF_INODE_INFO_MAGIC; 394 #endif 395 396 err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0); 397 if (err) { 398 LogFunc(("could not stat root of share\n")); 399 goto fail3; 400 } 401 402 sb->s_magic = 0xface; 403 sb->s_blocksize = 1024; 403 404 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 3) 404 405 /* Required for seek/sendfile (see 'loff_t max' in fs/read_write.c / do_sendfile()). */ 405 406 # if defined MAX_LFS_FILESIZE 406 407 sb->s_maxbytes = MAX_LFS_FILESIZE; 407 408 # elif BITS_PER_LONG == 32 408 409 sb->s_maxbytes = (loff_t)ULONG_MAX << PAGE_SHIFT; 409 410 # else 410 411 sb->s_maxbytes = INT64_MAX; 411 412 # endif 412 413 #endif 413 414 sb->s_op = &sf_super_ops; 414 415 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38) 415 416 sb->s_d_op = &sf_dentry_ops; 416 417 #endif 417 418 418 419 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) 419 420 iroot = iget_locked(sb, 0); 420 421 #else 421 422 #endif 423 424 err = -ENOMEM;/* XXX */425 426 427 428 429 430 431 422 iroot = iget(sb, 0); 423 #endif 424 if (!iroot) { 425 err = -ENOMEM; /* XXX */ 426 LogFunc(("could not get root inode\n")); 427 goto fail3; 428 } 429 430 if (sf_init_backing_dev(sb, sf_g)) { 431 err = -EINVAL; 432 LogFunc(("could not init bdi\n")); 432 433 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) 433 434 #endif 435 436 437 438 439 434 unlock_new_inode(iroot); 435 #endif 436 goto fail4; 437 } 438 439 sf_init_inode(iroot, sf_i, &fsinfo, sf_g); 440 SET_INODE_INFO(iroot, sf_i); 440 441 441 442 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) 442 443 unlock_new_inode(iroot); 443 444 #endif 444 445 445 446 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) 446 447 droot = d_make_root(iroot); 447 448 #else 448 449 #endif 450 451 err = -ENOMEM;/* XXX */452 449 droot = d_alloc_root(iroot); 450 #endif 451 if (!droot) { 452 err = -ENOMEM; /* XXX */ 453 LogFunc(("d_alloc_root failed\n")); 453 454 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) 454 455 #endif 456 457 458 459 460 461 455 fInodePut = false; 456 #endif 457 goto fail5; 458 } 459 460 sb->s_root = droot; 461 VBSF_SET_SUPER_INFO(sb, sf_g); 462 return 0; 462 463 463 464 fail5: 464 465 sf_done_backing_dev(sb, sf_g); 465 466 466 467 fail4: 467 468 468 if (fInodePut) 469 iput(iroot); 469 470 470 471 fail3: 471 472 kfree(sf_i->path); 472 473 473 474 fail2: 474 475 kfree(sf_i); 475 476 476 477 fail1: 477 478 sf_super_info_free(sf_g); 478 479 479 480 fail0: 480 481 return err; 481 482 } 482 483 … … 493 494 #endif 494 495 { 495 496 497 498 499 500 501 496 struct sf_inode_info *sf_i; 497 498 TRACE(); 499 500 /* 501 * Flush stuff. 502 */ 502 503 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) 503 504 truncate_inode_pages(&inode->i_data, 0); 504 505 # if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) 505 506 clear_inode(inode); 506 507 # else 507 508 end_writeback(inode); 508 509 # endif 509 510 #endif 510 511 512 513 514 515 516 517 518 519 520 511 /* 512 * Clean up our inode info. 513 */ 514 sf_i = GET_INODE_INFO(inode); 515 if (sf_i) { 516 SET_INODE_INFO(inode, NULL); 517 518 Assert(sf_i->u32Magic == SF_INODE_INFO_MAGIC); 519 BUG_ON(!sf_i->path); 520 kfree(sf_i->path); 521 sf_handle_drop_chain(sf_i); 521 522 # ifdef VBOX_STRICT 522 523 sf_i->u32Magic = SF_INODE_INFO_MAGIC_DEAD; 523 524 # endif 524 525 525 kfree(sf_i); 526 } 526 527 } 527 528 … … 542 543 static void sf_put_super(struct super_block *sb) 543 544 { 544 545 546 547 548 549 545 struct vbsf_super_info *sf_g; 546 547 sf_g = VBSF_GET_SUPER_INFO(sb); 548 BUG_ON(!sf_g); 549 sf_done_backing_dev(sb, sf_g); 550 sf_super_info_free(sf_g); 550 551 } 551 552 … … 563 564 { 564 565 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) 565 566 #endif 567 568 569 570 571 572 573 574 575 566 struct super_block *sb = dentry->d_inode->i_sb; 567 #endif 568 int rc; 569 VBOXSFVOLINFOREQ *pReq = (VBOXSFVOLINFOREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq)); 570 if (pReq) { 571 SHFLVOLINFO *pVolInfo = &pReq->VolInfo; 572 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(sb); 573 rc = VbglR0SfHostReqQueryVolInfo(sf_g->map.root, pReq, SHFL_HANDLE_ROOT); 574 if (RT_SUCCESS(rc)) { 575 stat->f_type = NFS_SUPER_MAGIC; /** @todo vboxsf type? */ 576 stat->f_bsize = pVolInfo->ulBytesPerAllocationUnit; 576 577 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 73) 577 578 #endif 579 580 581 582 583 584 585 586 587 588 589 590 578 stat->f_frsize = pVolInfo->ulBytesPerAllocationUnit; 579 #endif 580 stat->f_blocks = pVolInfo->ullTotalAllocationBytes 581 / pVolInfo->ulBytesPerAllocationUnit; 582 stat->f_bfree = pVolInfo->ullAvailableAllocationBytes 583 / pVolInfo->ulBytesPerAllocationUnit; 584 stat->f_bavail = pVolInfo->ullAvailableAllocationBytes 585 / pVolInfo->ulBytesPerAllocationUnit; 586 stat->f_files = 1000; 587 stat->f_ffree = 1000; /* don't return 0 here since the guest may think 588 * that it is not possible to create any more files */ 589 stat->f_fsid.val[0] = 0; 590 stat->f_fsid.val[1] = 0; 591 stat->f_namelen = 255; 591 592 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) 592 593 #endif 594 595 596 597 598 599 600 601 593 stat->f_flags = 0; /* not valid */ 594 #endif 595 RT_ZERO(stat->f_spare); 596 rc = 0; 597 } else 598 rc = -RTErrConvertToErrno(rc); 599 VbglR0PhysHeapFree(pReq); 600 } else 601 rc = -ENOMEM; 602 return rc; 602 603 } 603 604 … … 605 606 { 606 607 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 23) 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 608 struct vbsf_super_info *sf_g; 609 struct sf_inode_info *sf_i; 610 struct inode *iroot; 611 SHFLFSOBJINFO fsinfo; 612 int err; 613 614 sf_g = VBSF_GET_SUPER_INFO(sb); 615 BUG_ON(!sf_g); 616 if (data && data[0] != 0) { 617 struct vbsf_mount_info_new *info = (struct vbsf_mount_info_new *)data; 618 if ( info->nullchar == '\0' 619 && info->signature[0] == VBSF_MOUNT_SIGNATURE_BYTE_0 620 && info->signature[1] == VBSF_MOUNT_SIGNATURE_BYTE_1 621 && info->signature[2] == VBSF_MOUNT_SIGNATURE_BYTE_2) { 622 sf_super_info_copy_remount_options(sf_g, info); 623 } 624 } 625 626 iroot = ilookup(sb, 0); 627 if (!iroot) 628 return -ENOSYS; 629 630 sf_i = GET_INODE_INFO(iroot); 631 err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0); 632 BUG_ON(err != 0); 633 sf_init_inode(iroot, sf_i, &fsinfo, sf_g); 634 /*unlock_new_inode(iroot); */ 635 return 0; 635 636 #else /* LINUX_VERSION_CODE < 2.4.23 */ 636 637 return -ENOSYS; 637 638 #endif /* LINUX_VERSION_CODE < 2.4.23 */ 638 639 } … … 652 653 { 653 654 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) 654 655 struct super_block *sb = mnt->mnt_sb; 655 656 #else 656 657 #endif 658 659 660 661 662 663 664 665 666 667 668 657 struct super_block *sb = root->d_sb; 658 #endif 659 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(sb); 660 if (sf_g) { 661 seq_printf(m, ",uid=%u,gid=%u,ttl=%d,dmode=0%o,fmode=0%o,dmask=0%o,fmask=0%o,maxiopages=%u", 662 sf_g->uid, sf_g->gid, sf_g->ttl_msec, sf_g->dmode, sf_g->fmode, sf_g->dmask, 663 sf_g->fmask, sf_g->cMaxIoPages); 664 if (sf_g->tag[0] != '\0') { 665 seq_puts(m, ",tag="); 666 seq_escape(m, sf_g->tag, " \t\n\\"); 667 } 668 } 669 return 0; 669 670 } 670 671 … … 675 676 static struct super_operations sf_super_ops = { 676 677 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) 677 678 .clear_inode = sf_clear_inode, 678 679 #else 679 680 .evict_inode = sf_evict_inode, 680 681 #endif 681 682 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) 682 683 #endif 684 685 686 687 683 .read_inode = sf_read_inode, 684 #endif 685 .put_super = sf_put_super, 686 .statfs = sf_statfs, 687 .remount_fs = sf_remount_fs, 688 .show_options = sf_show_options 688 689 }; 689 690 … … 697 698 static int sf_read_super_26(struct super_block *sb, void *data, int flags) 698 699 { 699 700 701 702 703 704 705 706 700 int err; 701 702 TRACE(); 703 err = sf_read_super_aux(sb, data, flags); 704 if (err) 705 printk(KERN_DEBUG "sf_read_super_aux err=%d\n", err); 706 707 return err; 707 708 } 708 709 709 710 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) 710 711 static struct super_block *sf_get_sb(struct file_system_type *fs_type, 711 712 713 { 714 715 712 int flags, const char *dev_name, 713 void *data) 714 { 715 TRACE(); 716 return get_sb_nodev(fs_type, flags, data, sf_read_super_26); 716 717 } 717 718 # elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) 718 719 static int sf_get_sb(struct file_system_type *fs_type, int flags, 719 720 { 721 722 720 const char *dev_name, void *data, struct vfsmount *mnt) 721 { 722 TRACE(); 723 return get_sb_nodev(fs_type, flags, data, sf_read_super_26, mnt); 723 724 } 724 725 # else /* LINUX_VERSION_CODE >= 2.6.39 */ 725 726 static struct dentry *sf_mount(struct file_system_type *fs_type, int flags, 726 727 { 728 729 727 const char *dev_name, void *data) 728 { 729 TRACE(); 730 return mount_nodev(fs_type, flags, data, sf_read_super_26); 730 731 } 731 732 # endif /* LINUX_VERSION_CODE >= 2.6.39 */ 732 733 733 734 static struct file_system_type vboxsf_fs_type = { 734 735 735 .owner = THIS_MODULE, 736 .name = "vboxsf", 736 737 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) 737 738 .get_sb = sf_get_sb, 738 739 # else 739 740 .mount = sf_mount, 740 741 # endif 741 742 .kill_sb = kill_anon_super 742 743 }; 743 744 … … 745 746 746 747 static struct super_block *sf_read_super_24(struct super_block *sb, void *data, 747 748 { 749 750 751 752 753 754 755 756 757 758 748 int flags) 749 { 750 int err; 751 752 TRACE(); 753 err = sf_read_super_aux(sb, data, flags); 754 if (err) { 755 printk(KERN_DEBUG "sf_read_super_aux err=%d\n", err); 756 return NULL; 757 } 758 759 return sb; 759 760 } 760 761 … … 767 768 static int __init init(void) 768 769 { 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 770 int vrc; 771 int rcRet = 0; 772 int err; 773 774 TRACE(); 775 776 if (sizeof(struct vbsf_mount_info_new) > PAGE_SIZE) { 777 printk(KERN_ERR 778 "Mount information structure is too large %lu\n" 779 "Must be less than or equal to %lu\n", 780 (unsigned long)sizeof(struct vbsf_mount_info_new), 781 (unsigned long)PAGE_SIZE); 782 return -EINVAL; 783 } 784 785 /** @todo Init order is wrong, file system reigstration is the very last 786 * thing we should do. */ 787 spin_lock_init(&g_SfHandleLock); 788 err = register_filesystem(&vboxsf_fs_type); 789 if (err) { 790 LogFunc(("register_filesystem err=%d\n", err)); 791 return err; 792 } 793 794 vrc = VbglR0SfInit(); 795 if (RT_FAILURE(vrc)) { 796 LogRelFunc(("VbglR0SfInit failed, vrc=%Rrc\n", vrc)); 797 rcRet = -EPROTO; 798 goto fail0; 799 } 800 801 vrc = VbglR0SfConnect(&client_handle); 802 g_SfClient = client_handle; /* temporary */ 803 if (RT_FAILURE(vrc)) { 804 LogRelFunc(("VbglR0SfConnect failed, vrc=%Rrc\n", vrc)); 805 rcRet = -EPROTO; 806 goto fail1; 807 } 808 809 vrc = VbglR0QueryHostFeatures(&g_fHostFeatures); 810 if (RT_FAILURE(vrc)) 811 { 812 LogRelFunc(("VbglR0QueryHostFeatures failed: vrc=%Rrc (ignored)\n", vrc)); 813 g_fHostFeatures = 0; 814 } 815 LogRelFunc(("g_fHostFeatures=%#x\n", g_fHostFeatures)); 816 817 vrc = VbglR0SfSetUtf8(&client_handle); 818 if (RT_FAILURE(vrc)) { 819 LogRelFunc(("VbglR0SfSetUtf8 failed, vrc=%Rrc\n", vrc)); 820 rcRet = -EPROTO; 821 goto fail2; 822 } 822 823 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) 823 824 825 826 827 828 829 830 831 #endif 832 833 834 835 836 837 824 if (!g_fFollowSymlinks) { 825 vrc = VbglR0SfSetSymlinks(&client_handle); 826 if (RT_FAILURE(vrc)) { 827 printk(KERN_WARNING 828 "vboxsf: Host unable to show symlinks, vrc=%d\n", 829 vrc); 830 } 831 } 832 #endif 833 834 printk(KERN_DEBUG 835 "vboxsf: Successfully loaded version " VBOX_VERSION_STRING 836 " (interface " RT_XSTR(VMMDEV_VERSION) ")\n"); 837 838 return 0; 838 839 839 840 fail2: 840 841 841 VbglR0SfDisconnect(&client_handle); 842 g_SfClient = client_handle; /* temporary */ 842 843 843 844 fail1: 844 845 VbglR0SfTerm(); 845 846 846 847 fail0: 847 848 848 unregister_filesystem(&vboxsf_fs_type); 849 return rcRet; 849 850 } 850 851 851 852 static void __exit fini(void) 852 853 { 853 854 855 856 857 858 854 TRACE(); 855 856 VbglR0SfDisconnect(&client_handle); 857 g_SfClient = client_handle; /* temporary */ 858 VbglR0SfTerm(); 859 unregister_filesystem(&vboxsf_fs_type); 859 860 } 860 861 … … 866 867 module_param_named(follow_symlinks, g_fFollowSymlinks, int, 0); 867 868 MODULE_PARM_DESC(follow_symlinks, 868 869 "Let host resolve symlinks rather than showing them"); 869 870 #endif 870 871 -
trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.h
r77524 r77526 63 63 DECLINLINE(loff_t) i_size_read(struct inode *pInode) 64 64 { 65 66 65 AssertCompile(sizeof(loff_t) == sizeof(uint64_t)); 66 return ASMAtomicReadU64((uint64_t volatile *)&pInode->i_size); 67 67 } 68 68 69 69 DECLINLINE(void) i_size_write(struct inode *pInode, loff_t cbNew) 70 70 { 71 72 71 AssertCompile(sizeof(pInode->i_size) == sizeof(uint64_t)); 72 ASMAtomicWriteU64((uint64_t volatile *)&pInode->i_size, cbNew); 73 73 } 74 74 … … 78 78 DECLINLINE(void) set_nlink(struct inode *pInode, unsigned int cLinks) 79 79 { 80 80 pInode->i_nlink = cLinks; 81 81 } 82 82 #endif … … 89 89 */ 90 90 struct vbsf_super_info { 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 91 VBGLSFMAP map; 92 struct nls_table *nls; 93 /** time-to-live value for direntry and inode info in jiffies. 94 * Zero == disabled. */ 95 unsigned long ttl; 96 /** The mount option value for /proc/mounts. */ 97 int ttl_msec; 98 int uid; 99 int gid; 100 int dmode; 101 int fmode; 102 int dmask; 103 int fmask; 104 /** Maximum number of pages to allow in an I/O buffer with the host. 105 * This applies to read and write operations. */ 106 uint32_t cMaxIoPages; 107 /** Mount tag for VBoxService automounter. @since 6.0 */ 108 char tag[32]; 109 109 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) 110 111 110 /** The backing device info structure. */ 111 struct backing_dev_info bdi; 112 112 #endif 113 113 }; … … 131 131 */ 132 132 struct sf_handle { 133 134 135 136 137 138 139 140 141 133 /** List entry (head sf_inode_info::HandleList). */ 134 RTLISTNODE Entry; 135 /** Host file/whatever handle. */ 136 SHFLHANDLE hHost; 137 /** SF_HANDLE_F_XXX */ 138 uint32_t fFlags; 139 /** Reference counter. 140 * Close the handle and free the structure when it reaches zero. */ 141 uint32_t volatile cRefs; 142 142 #ifdef VBOX_STRICT 143 144 143 /** For strictness checks. */ 144 struct sf_inode_info *pInodeInfo; 145 145 #endif 146 146 }; … … 154 154 #define SF_HANDLE_F_ON_LIST UINT32_C(0x00000080) 155 155 #define SF_HANDLE_F_MAGIC_MASK UINT32_C(0xffffff00) 156 #define SF_HANDLE_F_MAGIC 156 #define SF_HANDLE_F_MAGIC UINT32_C(0x75030700) /**< Maurice Ravel (1875-03-07). */ 157 157 #define SF_HANDLE_F_MAGIC_DEAD UINT32_C(0x19371228) 158 158 /** @} */ … … 162 162 */ 163 163 struct sf_inode_info { 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 RTLISTANCHORHandleList;164 /** Which file */ 165 SHFLSTRING *path; 166 /** Some information was changed, update data on next revalidate */ 167 bool force_restat; 168 /** directory content changed, update the whole directory on next sf_getdent */ 169 bool force_reread; 170 /** The timestamp (jiffies) where the inode info was last updated. */ 171 unsigned long ts_up_to_date; 172 /** The birth time. */ 173 RTTIMESPEC BirthTime; 174 175 /** handle valid if a file was created with sf_create_aux until it will 176 * be opened with sf_reg_open() 177 * @todo r=bird: figure this one out... */ 178 SHFLHANDLE handle; 179 180 /** List of open handles (struct sf_handle), protected by g_SfHandleLock. */ 181 RTLISTANCHOR HandleList; 182 182 #ifdef VBOX_STRICT 183 183 uint32_t u32Magic; 184 184 # define SF_INODE_INFO_MAGIC UINT32_C(0x18620822) /**< Claude Debussy */ 185 185 # define SF_INODE_INFO_MAGIC_DEAD UINT32_C(0x19180325) … … 188 188 189 189 struct sf_dir_info { 190 191 190 /** @todo sf_handle. */ 191 struct list_head info_list; 192 192 }; 193 193 194 194 struct sf_dir_buf { 195 196 197 198 199 195 size_t cEntries; 196 size_t cbFree; 197 size_t cbUsed; 198 void *buf; 199 struct list_head head; 200 200 }; 201 201 … … 204 204 */ 205 205 struct sf_reg_info { 206 207 206 /** Handle tracking structure. */ 207 struct sf_handle Handle; 208 208 }; 209 209 … … 235 235 * Increase the time-to-live of @a pDirEntry and all ancestors. 236 236 * @param pDirEntry The directory entry cache entry which ancestors 237 * 237 * we should increase the TTL for. 238 238 */ 239 239 DECLINLINE(void) sf_dentry_chain_increase_ttl(struct dentry *pDirEntry) 240 240 { 241 241 #ifdef VBOX_STRICT 242 243 #endif 244 245 246 247 248 249 242 struct super_block * const pSuper = pDirEntry->d_sb; 243 #endif 244 unsigned long const uToSet = jiffies; 245 do { 246 Assert(pDirEntry->d_sb == pSuper); 247 sf_dentry_set_update_jiffies(pDirEntry, uToSet); 248 pDirEntry = pDirEntry->d_parent; 249 } while (!IS_ROOT(pDirEntry)); 250 250 } 251 251 … … 253 253 * Increase the time-to-live of all ancestors. 254 254 * @param pDirEntry The directory entry cache entry which ancestors 255 * 255 * we should increase the TTL for. 256 256 */ 257 257 DECLINLINE(void) sf_dentry_chain_increase_parent_ttl(struct dentry *pDirEntry) 258 258 { 259 260 261 262 259 Assert(!pDirEntry->d_parent || pDirEntry->d_parent->d_sb == pDirEntry->d_sb); 260 pDirEntry = pDirEntry->d_parent; 261 if (pDirEntry) 262 sf_dentry_chain_increase_ttl(pDirEntry); 263 263 } 264 264 … … 289 289 * @param pHandle The handle to release. 290 290 * @param sf_g The info structure for the shared folder associated 291 * 291 * with the handle. 292 292 * @param pszCaller The caller name (for logging failures). 293 293 */ 294 294 DECLINLINE(uint32_t) sf_handle_release(struct sf_handle *pHandle, struct vbsf_super_info *sf_g, const char *pszCaller) 295 295 { 296 297 298 299 300 301 302 303 304 305 306 296 uint32_t cRefs; 297 298 Assert((pHandle->fFlags & SF_HANDLE_F_MAGIC_MASK) == SF_HANDLE_F_MAGIC); 299 Assert(pHandle->pInodeInfo); 300 Assert(pHandle->pInodeInfo && pHandle->pInodeInfo->u32Magic == SF_INODE_INFO_MAGIC); 301 302 cRefs = ASMAtomicDecU32(&pHandle->cRefs); 303 Assert(cRefs < _64M); 304 if (cRefs) 305 return cRefs; 306 return sf_handle_release_slow(pHandle, sf_g, pszCaller); 307 307 } 308 308 309 309 extern void sf_init_inode(struct inode *inode, struct sf_inode_info *sf_i, PSHFLFSOBJINFO info, struct vbsf_super_info *sf_g); 310 310 extern int sf_stat(const char *caller, struct vbsf_super_info *sf_g, 311 311 SHFLSTRING * path, PSHFLFSOBJINFO result, int ok_to_fail); 312 312 extern int sf_inode_revalidate(struct dentry *dentry); 313 313 extern int sf_inode_revalidate_worker(struct dentry *dentry, bool fForced); … … 316 316 # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) 317 317 extern int sf_getattr(const struct path *path, struct kstat *kstat, 318 318 u32 request_mask, unsigned int query_flags); 319 319 # else 320 320 extern int sf_getattr(struct vfsmount *mnt, struct dentry *dentry, 321 321 struct kstat *kstat); 322 322 # endif 323 323 extern int sf_setattr(struct dentry *dentry, struct iattr *iattr); 324 324 #endif 325 325 extern int sf_path_from_dentry(const char *caller, struct vbsf_super_info *sf_g, 326 327 326 struct sf_inode_info *sf_i, 327 struct dentry *dentry, SHFLSTRING ** result); 328 328 extern int sf_nlscpy(struct vbsf_super_info *sf_g, char *name, 329 330 329 size_t name_bound_len, const unsigned char *utf8_name, 330 size_t utf8_len); 331 331 extern void sf_dir_info_free(struct sf_dir_info *p); 332 332 extern void sf_dir_info_empty(struct sf_dir_info *p); 333 333 extern struct sf_dir_info *sf_dir_info_alloc(void); 334 334 extern int sf_dir_read_all(struct vbsf_super_info *sf_g, 335 336 335 struct sf_inode_info *sf_i, struct sf_dir_info *sf_d, 336 SHFLHANDLE handle); 337 337 338 338 #ifdef __cplusplus
Note:
See TracChangeset
for help on using the changeset viewer.