Changes in uspace/srv/vfs/vfs_ops.c [08232ee:6a4e972] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/vfs/vfs_ops.c
r08232ee r6a4e972 92 92 } 93 93 94 rc = vfs_lookup_internal(mp, L_ DIRECTORY, &mp_res, NULL);94 rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL); 95 95 if (rc != EOK) { 96 96 /* The lookup failed for some reason. */ … … 429 429 } 430 430 431 void vfs_unmount(ipc_callid_t rid, ipc_call_t *request) 432 { 433 int rc; 434 char *mp; 435 vfs_lookup_res_t mp_res; 436 vfs_lookup_res_t mr_res; 437 vfs_node_t *mp_node; 438 vfs_node_t *mr_node; 439 int phone; 440 441 /* 442 * Receive the mount point path. 443 */ 444 rc = async_data_string_receive(&mp, MAX_PATH_LEN); 445 if (rc != EOK) 446 ipc_answer_0(rid, rc); 447 448 /* 449 * Taking the namespace lock will do two things for us. First, it will 450 * prevent races with other lookup operations. Second, it will stop new 451 * references to already existing VFS nodes and creation of new VFS 452 * nodes. This is because new references are added as a result of some 453 * lookup operation or at least of some operation which is protected by 454 * the namespace lock. 455 */ 456 fibril_rwlock_write_lock(&namespace_rwlock); 457 458 /* 459 * Lookup the mounted root and instantiate it. 460 */ 461 rc = vfs_lookup_internal(mp, L_ROOT, &mr_res, NULL); 462 if (rc != EOK) { 463 fibril_rwlock_write_unlock(&namespace_rwlock); 464 free(mp); 465 ipc_answer_0(rid, rc); 466 return; 467 } 468 mr_node = vfs_node_get(&mr_res); 469 if (!mr_node) { 470 fibril_rwlock_write_unlock(&namespace_rwlock); 471 free(mp); 472 ipc_answer_0(rid, ENOMEM); 473 return; 474 } 475 476 /* 477 * Count the total number of references for the mounted file system. We 478 * are expecting at least two. One which we got above and one which we 479 * got when the file system was mounted. If we find more, it means that 480 * the file system cannot be gracefully unmounted at the moment because 481 * someone is working with it. 482 */ 483 if (vfs_nodes_refcount_sum_get(mr_node->fs_handle, 484 mr_node->dev_handle) != 2) { 485 fibril_rwlock_write_unlock(&namespace_rwlock); 486 vfs_node_put(mr_node); 487 free(mp); 488 ipc_answer_0(rid, EBUSY); 489 return; 490 } 491 492 if (str_cmp(mp, "/") == 0) { 493 494 /* 495 * Unmounting the root file system. 496 * 497 * In this case, there is no mount point node and we send 498 * VFS_OUT_UNMOUNTED directly to the mounted file system. 499 */ 500 501 free(mp); 502 phone = vfs_grab_phone(mr_node->fs_handle); 503 rc = async_req_1_0(phone, VFS_OUT_UNMOUNTED, 504 mr_node->dev_handle); 505 vfs_release_phone(phone); 506 if (rc != EOK) { 507 fibril_rwlock_write_unlock(&namespace_rwlock); 508 vfs_node_put(mr_node); 509 ipc_answer_0(rid, rc); 510 return; 511 } 512 rootfs.fs_handle = 0; 513 rootfs.dev_handle = 0; 514 } else { 515 516 /* 517 * Unmounting a non-root file system. 518 * 519 * We have a regular mount point node representing the parent 520 * file system, so we delegate the operation to it. 521 */ 522 523 rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL); 524 free(mp); 525 if (rc != EOK) { 526 fibril_rwlock_write_unlock(&namespace_rwlock); 527 vfs_node_put(mr_node); 528 ipc_answer_0(rid, rc); 529 return; 530 } 531 vfs_node_t *mp_node = vfs_node_get(&mp_res); 532 if (!mp_node) { 533 fibril_rwlock_write_unlock(&namespace_rwlock); 534 vfs_node_put(mr_node); 535 ipc_answer_0(rid, ENOMEM); 536 return; 537 } 538 539 phone = vfs_grab_phone(mp_node->fs_handle); 540 rc = async_req_2_0(phone, VFS_OUT_UNMOUNT, mp_node->dev_handle, 541 mp_node->index); 542 vfs_release_phone(phone); 543 if (rc != EOK) { 544 fibril_rwlock_write_unlock(&namespace_rwlock); 545 vfs_node_put(mp_node); 546 vfs_node_put(mr_node); 547 ipc_answer_0(rid, rc); 548 return; 549 } 550 551 /* Drop the reference we got above. */ 552 vfs_node_put(mp_node); 553 /* Drop the reference from when the file system was mounted. */ 554 vfs_node_put(mp_node); 555 } 556 557 558 /* 559 * All went well, the mounted file system was successfully unmounted. 560 * The only thing left is to forget the unmounted root VFS node. 561 */ 562 vfs_node_forget(mr_node); 563 564 fibril_rwlock_write_unlock(&namespace_rwlock); 565 ipc_answer_0(rid, EOK); 566 } 567 431 568 void vfs_open(ipc_callid_t rid, ipc_call_t *request) 432 569 { … … 454 591 /* 455 592 * Make sure that we are called with exactly one of L_FILE and 456 * L_DIRECTORY. Make sure that the user does not pass L_OPEN. 593 * L_DIRECTORY. Make sure that the user does not pass L_OPEN, 594 * L_ROOT or L_MP. 457 595 */ 458 596 if (((lflag & (L_FILE | L_DIRECTORY)) == 0) || 459 597 ((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) || 460 ( (lflag & L_OPEN) != 0)) {598 (lflag & (L_OPEN | L_ROOT | L_MP))) { 461 599 ipc_answer_0(rid, EINVAL); 462 600 return;
Note:
See TracChangeset
for help on using the changeset viewer.