Changeset ae75e2e3 in mainline
- Timestamp:
- 2010-01-24T17:30:37Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- e095644, f7376cbf
- Parents:
- c4aca2c
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/vfs/vfs_ops.c
rc4aca2c rae75e2e3 431 431 void vfs_unmount(ipc_callid_t rid, ipc_call_t *request) 432 432 { 433 ipc_answer_0(rid, ENOTSUP); 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_NONE, &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 /* 524 * The L_NOCROSS_LAST_MP flag is essential if we really want to 525 * lookup the mount point and not the mounted root. 526 */ 527 rc = vfs_lookup_internal(mp, L_NOCROSS_LAST_MP, &mp_res, NULL); 528 free(mp); 529 if (rc != EOK) { 530 fibril_rwlock_write_unlock(&namespace_rwlock); 531 vfs_node_put(mr_node); 532 ipc_answer_0(rid, rc); 533 return; 534 } 535 vfs_node_t *mp_node = vfs_node_get(&mp_res); 536 if (!mp_node) { 537 fibril_rwlock_write_unlock(&namespace_rwlock); 538 vfs_node_put(mr_node); 539 ipc_answer_0(rid, ENOMEM); 540 return; 541 } 542 543 phone = vfs_grab_phone(mp_node->fs_handle); 544 rc = async_req_2_0(phone, VFS_OUT_UNMOUNT, mp_node->fs_handle, 545 mp_node->dev_handle); 546 vfs_release_phone(phone); 547 if (rc != EOK) { 548 fibril_rwlock_write_unlock(&namespace_rwlock); 549 vfs_node_put(mp_node); 550 vfs_node_put(mr_node); 551 ipc_answer_0(rid, rc); 552 return; 553 } 554 555 /* Drop the reference we got above. */ 556 vfs_node_put(mp_node); 557 /* Drop the reference from when the file system was mounted. */ 558 vfs_node_put(mp_node); 559 } 560 561 562 /* 563 * All went well, the mounted file system was successfully unmounted. 564 * The only thing left is to forget the unmounted root VFS node. 565 */ 566 vfs_node_forget(mr_node); 567 568 fibril_rwlock_write_unlock(&namespace_rwlock); 569 ipc_answer_0(rid, EOK); 434 570 } 435 571
Note:
See TracChangeset
for help on using the changeset viewer.