Changes in uspace/srv/vfs/vfs_ops.c [ae75e2e3:08232ee] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/vfs/vfs_ops.c
rae75e2e3 r08232ee 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 will450 * prevent races with other lookup operations. Second, it will stop new451 * references to already existing VFS nodes and creation of new VFS452 * nodes. This is because new references are added as a result of some453 * lookup operation or at least of some operation which is protected by454 * 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. We478 * are expecting at least two. One which we got above and one which we479 * got when the file system was mounted. If we find more, it means that480 * the file system cannot be gracefully unmounted at the moment because481 * 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 send498 * 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 parent520 * 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 to525 * 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);570 }571 572 431 void vfs_open(ipc_callid_t rid, ipc_call_t *request) 573 432 { … … 595 454 /* 596 455 * Make sure that we are called with exactly one of L_FILE and 597 * L_DIRECTORY. Make sure that the user does not pass L_OPEN or 598 * L_NOCROSS_LAST_MP. 456 * L_DIRECTORY. Make sure that the user does not pass L_OPEN. 599 457 */ 600 458 if (((lflag & (L_FILE | L_DIRECTORY)) == 0) || 601 459 ((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) || 602 ( lflag & L_OPEN) || (lflag & L_NOCROSS_LAST_MP)) {460 ((lflag & L_OPEN) != 0)) { 603 461 ipc_answer_0(rid, EINVAL); 604 462 return;
Note:
See TracChangeset
for help on using the changeset viewer.