Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/vfs/vfs_ops.c

    r1e4cada r6a4e972  
    9292                }
    9393               
    94                 rc = vfs_lookup_internal(mp, L_DIRECTORY, &mp_res, NULL);
     94                rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL);
    9595                if (rc != EOK) {
    9696                        /* The lookup failed for some reason. */
     
    429429}
    430430
     431void 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
    431568void vfs_open(ipc_callid_t rid, ipc_call_t *request)
    432569{
     
    454591        /*
    455592         * 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.
    457595         */
    458596        if (((lflag & (L_FILE | L_DIRECTORY)) == 0) ||
    459597            ((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) ||
    460             ((lflag & L_OPEN) != 0)) {
     598            (lflag & (L_OPEN | L_ROOT | L_MP))) {
    461599                ipc_answer_0(rid, EINVAL);
    462600                return;
     
    9001038                }
    9011039                newpos = size + off;
     1040                file->pos = newpos;
    9021041                fibril_mutex_unlock(&file->lock);
    9031042                ipc_answer_1(rid, EOK, newpos);
Note: See TracChangeset for help on using the changeset viewer.