Ignore:
File:
1 edited

Legend:

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

    re6da6d5 rccca251  
    5252#include <assert.h>
    5353#include <vfs/canonify.h>
    54 #include <vfs/vfs_mtab.h>
    55 
    56 FIBRIL_MUTEX_INITIALIZE(mtab_list_lock);
    57 LIST_INITIALIZE(mtab_list);
    58 static size_t mtab_size = 0;
    5954
    6055/* Forward declarations of static functions. */
    61 static int vfs_truncate_internal(fs_handle_t, service_id_t, fs_index_t,
     56static int vfs_truncate_internal(fs_handle_t, devmap_handle_t, fs_index_t,
    6257    aoff64_t);
    6358
     
    7065vfs_pair_t rootfs = {
    7166        .fs_handle = 0,
    72         .service_id = 0
     67        .devmap_handle = 0
    7368};
    7469
    75 static int vfs_mount_internal(ipc_callid_t rid, service_id_t service_id,
     70static void vfs_mount_internal(ipc_callid_t rid, devmap_handle_t devmap_handle,
    7671    fs_handle_t fs_handle, char *mp, char *opts)
    7772{
     
    8176        vfs_node_t *mr_node;
    8277        fs_index_t rindex;
    83         aoff64_t rsize;
     78        size_t rsize;
    8479        unsigned rlnkcnt;
    85         async_exch_t *exch;
    8680        sysarg_t rc;
     81        int phone;
    8782        aid_t msg;
    8883        ipc_call_t answer;
     
    9691                        fibril_rwlock_write_unlock(&namespace_rwlock);
    9792                        async_answer_0(rid, EBUSY);
    98                         return EBUSY;
     93                        return;
    9994                }
    10095               
     
    10499                        fibril_rwlock_write_unlock(&namespace_rwlock);
    105100                        async_answer_0(rid, rc);
    106                         return rc;
     101                        return;
    107102                }
    108103               
     
    111106                        fibril_rwlock_write_unlock(&namespace_rwlock);
    112107                        async_answer_0(rid, ENOMEM);
    113                         return ENOMEM;
     108                        return;
    114109                }
    115110               
     
    128123                       
    129124                        /* Tell the mountee that it is being mounted. */
    130                         exch = vfs_exchange_grab(fs_handle);
    131                         msg = async_send_1(exch, VFS_OUT_MOUNTED,
    132                             (sysarg_t) service_id, &answer);
    133                         /* Send the mount options */
    134                         rc = async_data_write_start(exch, (void *)opts,
     125                        phone = vfs_grab_phone(fs_handle);
     126                        msg = async_send_1(phone, VFS_OUT_MOUNTED,
     127                            (sysarg_t) devmap_handle, &answer);
     128                        /* send the mount options */
     129                        rc = async_data_write_start(phone, (void *)opts,
    135130                            str_size(opts));
    136                         vfs_exchange_release(exch);
    137                        
    138131                        if (rc != EOK) {
    139132                                async_wait_for(msg, NULL);
     133                                vfs_release_phone(fs_handle, phone);
    140134                                fibril_rwlock_write_unlock(&namespace_rwlock);
    141135                                async_answer_0(rid, rc);
    142                                 return rc;
     136                                return;
    143137                        }
    144138                        async_wait_for(msg, &rc);
     139                        vfs_release_phone(fs_handle, phone);
    145140                       
    146141                        if (rc != EOK) {
    147142                                fibril_rwlock_write_unlock(&namespace_rwlock);
    148143                                async_answer_0(rid, rc);
    149                                 return rc;
     144                                return;
    150145                        }
    151146
    152147                        rindex = (fs_index_t) IPC_GET_ARG1(answer);
    153                         rsize = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(answer),
    154                             IPC_GET_ARG3(answer));
    155                         rlnkcnt = (unsigned) IPC_GET_ARG4(answer);
     148                        rsize = (size_t) IPC_GET_ARG2(answer);
     149                        rlnkcnt = (unsigned) IPC_GET_ARG3(answer);
    156150                       
    157151                        mr_res.triplet.fs_handle = fs_handle;
    158                         mr_res.triplet.service_id = service_id;
     152                        mr_res.triplet.devmap_handle = devmap_handle;
    159153                        mr_res.triplet.index = rindex;
    160154                        mr_res.size = rsize;
     
    163157                       
    164158                        rootfs.fs_handle = fs_handle;
    165                         rootfs.service_id = service_id;
     159                        rootfs.devmap_handle = devmap_handle;
    166160                       
    167161                        /* Add reference to the mounted root. */
     
    171165                        fibril_rwlock_write_unlock(&namespace_rwlock);
    172166                        async_answer_0(rid, rc);
    173                         return rc;
     167                        return;
    174168                } else {
    175169                        /*
     
    179173                        fibril_rwlock_write_unlock(&namespace_rwlock);
    180174                        async_answer_0(rid, ENOENT);
    181                         return ENOENT;
    182                 }
    183         }
    184        
    185         /*
    186          * At this point, we have all necessary pieces: file system handle
    187          * and service ID, and we know the mount point VFS node.
    188          */
    189        
    190         async_exch_t *mountee_exch = vfs_exchange_grab(fs_handle);
    191         assert(mountee_exch);
    192        
    193         exch = vfs_exchange_grab(mp_res.triplet.fs_handle);
    194         msg = async_send_4(exch, VFS_OUT_MOUNT,
    195             (sysarg_t) mp_res.triplet.service_id,
     175                        return;
     176                }
     177        }
     178       
     179        /*
     180         * At this point, we have all necessary pieces: file system and device
     181         * handles, and we know the mount point VFS node.
     182         */
     183       
     184        int mountee_phone = vfs_grab_phone(fs_handle);
     185        assert(mountee_phone >= 0);
     186
     187        phone = vfs_grab_phone(mp_res.triplet.fs_handle);
     188        msg = async_send_4(phone, VFS_OUT_MOUNT,
     189            (sysarg_t) mp_res.triplet.devmap_handle,
    196190            (sysarg_t) mp_res.triplet.index,
    197191            (sysarg_t) fs_handle,
    198             (sysarg_t) service_id, &answer);
    199        
    200         /* Send connection */
    201         rc = async_exchange_clone(exch, mountee_exch);
    202         vfs_exchange_release(mountee_exch);
    203        
    204         if (rc != EOK) {
    205                 vfs_exchange_release(exch);
     192            (sysarg_t) devmap_handle, &answer);
     193       
     194        /* send connection */
     195        rc = async_req_1_0(phone, IPC_M_CONNECTION_CLONE, mountee_phone);
     196        if (rc != EOK) {
    206197                async_wait_for(msg, NULL);
    207                
     198                vfs_release_phone(fs_handle, mountee_phone);
     199                vfs_release_phone(mp_res.triplet.fs_handle, phone);
    208200                /* Mount failed, drop reference to mp_node. */
    209201                if (mp_node)
    210202                        vfs_node_put(mp_node);
    211                
    212203                async_answer_0(rid, rc);
    213204                fibril_rwlock_write_unlock(&namespace_rwlock);
    214                 return rc;
    215         }
     205                return;
     206        }
     207
     208        vfs_release_phone(fs_handle, mountee_phone);
    216209       
    217210        /* send the mount options */
    218         rc = async_data_write_start(exch, (void *) opts, str_size(opts));
    219         if (rc != EOK) {
    220                 vfs_exchange_release(exch);
     211        rc = async_data_write_start(phone, (void *)opts, str_size(opts));
     212        if (rc != EOK) {
    221213                async_wait_for(msg, NULL);
    222                
     214                vfs_release_phone(mp_res.triplet.fs_handle, phone);
    223215                /* Mount failed, drop reference to mp_node. */
    224216                if (mp_node)
    225217                        vfs_node_put(mp_node);
    226                
    227218                fibril_rwlock_write_unlock(&namespace_rwlock);
    228219                async_answer_0(rid, rc);
    229                 return rc;
    230         }
    231        
    232         /*
    233          * Wait for the answer before releasing the exchange to avoid deadlock
    234          * in case the answer depends on further calls to the same file system.
    235          * Think of a case when mounting a FS on a file_bd backed by a file on
    236          * the same FS.
    237          */
     220                return;
     221        }
    238222        async_wait_for(msg, &rc);
    239         vfs_exchange_release(exch);
     223        vfs_release_phone(mp_res.triplet.fs_handle, phone);
    240224       
    241225        if (rc == EOK) {
    242226                rindex = (fs_index_t) IPC_GET_ARG1(answer);
    243                 rsize = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(answer),
    244                     IPC_GET_ARG3(answer));
    245                 rlnkcnt = (unsigned) IPC_GET_ARG4(answer);
    246                
     227                rsize = (size_t) IPC_GET_ARG2(answer);
     228                rlnkcnt = (unsigned) IPC_GET_ARG3(answer);
     229       
    247230                mr_res.triplet.fs_handle = fs_handle;
    248                 mr_res.triplet.service_id = service_id;
     231                mr_res.triplet.devmap_handle = devmap_handle;
    249232                mr_res.triplet.index = rindex;
    250233                mr_res.size = rsize;
    251234                mr_res.lnkcnt = rlnkcnt;
    252235                mr_res.type = VFS_NODE_DIRECTORY;
    253                
     236       
    254237                /* Add reference to the mounted root. */
    255238                mr_node = vfs_node_get(&mr_res);
     
    260243                        vfs_node_put(mp_node);
    261244        }
    262        
     245
    263246        async_answer_0(rid, rc);
    264247        fibril_rwlock_write_unlock(&namespace_rwlock);
    265         return rc;
    266248}
    267249
    268250void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
    269251{
    270         service_id_t service_id;
     252        devmap_handle_t devmap_handle;
    271253
    272254        /*
     
    275257         * in the request.
    276258         */
    277         service_id = (service_id_t) IPC_GET_ARG1(*request);
     259        devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    278260       
    279261        /*
     
    283265       
    284266        /*
    285          * Instance number is passed as ARG3.
    286          */
    287         unsigned int instance = IPC_GET_ARG3(*request);
    288 
     267         * For now, don't make use of ARG3, but it can be used to
     268         * carry mount options in the future.
     269         */
     270       
    289271        /* We want the client to send us the mount point. */
    290272        char *mp;
     
    321303       
    322304        /*
    323          * Wait for VFS_IN_PING so that we can return an error if we don't know
     305         * Wait for IPC_M_PING so that we can return an error if we don't know
    324306         * fs_name.
    325307         */
    326308        ipc_call_t data;
    327309        ipc_callid_t callid = async_get_call(&data);
    328         if (IPC_GET_IMETHOD(data) != VFS_IN_PING) {
     310        if (IPC_GET_IMETHOD(data) != IPC_M_PING) {
    329311                async_answer_0(callid, ENOTSUP);
    330312                async_answer_0(rid, ENOTSUP);
     
    339321         * This will also give us its file system handle.
    340322         */
    341         fibril_mutex_lock(&fs_list_lock);
     323        fibril_mutex_lock(&fs_head_lock);
    342324        fs_handle_t fs_handle;
    343325recheck:
    344         fs_handle = fs_name_to_handle(instance, fs_name, false);
     326        fs_handle = fs_name_to_handle(fs_name, false);
    345327        if (!fs_handle) {
    346328                if (flags & IPC_FLAG_BLOCKING) {
    347                         fibril_condvar_wait(&fs_list_cv, &fs_list_lock);
     329                        fibril_condvar_wait(&fs_head_cv, &fs_head_lock);
    348330                        goto recheck;
    349331                }
    350332               
    351                 fibril_mutex_unlock(&fs_list_lock);
     333                fibril_mutex_unlock(&fs_head_lock);
    352334                async_answer_0(callid, ENOENT);
    353335                async_answer_0(rid, ENOENT);
     
    357339                return;
    358340        }
    359         fibril_mutex_unlock(&fs_list_lock);
    360 
    361         /* Add the filesystem info to the list of mounted filesystems */
    362         mtab_ent_t *mtab_ent = malloc(sizeof(mtab_ent_t));
    363         if (!mtab_ent) {
    364                 async_answer_0(callid, ENOMEM);
    365                 async_answer_0(rid, ENOMEM);
    366                 free(mp);
    367                 free(fs_name);
    368                 free(opts);
    369                 return;
    370         }
    371 
     341        fibril_mutex_unlock(&fs_head_lock);
     342       
     343        /* Acknowledge that we know fs_name. */
     344        async_answer_0(callid, EOK);
     345       
    372346        /* Do the mount */
    373         rc = vfs_mount_internal(rid, service_id, fs_handle, mp, opts);
    374         if (rc != EOK) {
    375                 async_answer_0(callid, ENOTSUP);
    376                 async_answer_0(rid, ENOTSUP);
    377                 free(mtab_ent);
    378                 free(mp);
    379                 free(opts);
    380                 free(fs_name);
    381                 return;
    382         }
    383 
    384         /* Add the filesystem info to the list of mounted filesystems */
    385 
    386         str_cpy(mtab_ent->mp, MAX_PATH_LEN, mp);
    387         str_cpy(mtab_ent->fs_name, FS_NAME_MAXLEN, fs_name);
    388         str_cpy(mtab_ent->opts, MAX_MNTOPTS_LEN, opts);
    389         mtab_ent->instance = instance;
    390         mtab_ent->service_id = service_id;
    391 
    392         link_initialize(&mtab_ent->link);
    393 
    394         fibril_mutex_lock(&mtab_list_lock);
    395         list_append(&mtab_ent->link, &mtab_list);
    396         mtab_size++;
    397         fibril_mutex_unlock(&mtab_list_lock);
    398 
     347        vfs_mount_internal(rid, devmap_handle, fs_handle, mp, opts);
    399348        free(mp);
    400349        free(fs_name);
    401350        free(opts);
    402 
    403         /* Acknowledge that we know fs_name. */
    404         async_answer_0(callid, EOK);
    405351}
    406352
     
    412358        vfs_lookup_res_t mr_res;
    413359        vfs_node_t *mr_node;
    414         async_exch_t *exch;
    415        
     360        int phone;
     361
    416362        /*
    417363         * Receive the mount point path.
     
    421367        if (rc != EOK)
    422368                async_answer_0(rid, rc);
    423        
     369
    424370        /*
    425371         * Taking the namespace lock will do two things for us. First, it will
     
    449395                return;
    450396        }
    451        
     397
    452398        /*
    453399         * Count the total number of references for the mounted file system. We
     
    458404         */
    459405        if (vfs_nodes_refcount_sum_get(mr_node->fs_handle,
    460             mr_node->service_id) != 2) {
     406            mr_node->devmap_handle) != 2) {
    461407                fibril_rwlock_write_unlock(&namespace_rwlock);
    462408                vfs_node_put(mr_node);
     
    465411                return;
    466412        }
    467        
     413
    468414        if (str_cmp(mp, "/") == 0) {
    469                
     415
    470416                /*
    471417                 * Unmounting the root file system.
     
    474420                 * VFS_OUT_UNMOUNTED directly to the mounted file system.
    475421                 */
    476                
    477                 exch = vfs_exchange_grab(mr_node->fs_handle);
    478                 rc = async_req_1_0(exch, VFS_OUT_UNMOUNTED,
    479                     mr_node->service_id);
    480                 vfs_exchange_release(exch);
    481                
     422
     423                free(mp);
     424                phone = vfs_grab_phone(mr_node->fs_handle);
     425                rc = async_req_1_0(phone, VFS_OUT_UNMOUNTED,
     426                    mr_node->devmap_handle);
     427                vfs_release_phone(mr_node->fs_handle, phone);
    482428                if (rc != EOK) {
    483429                        fibril_rwlock_write_unlock(&namespace_rwlock);
    484                         free(mp);
    485430                        vfs_node_put(mr_node);
    486431                        async_answer_0(rid, rc);
    487432                        return;
    488433                }
    489                
    490434                rootfs.fs_handle = 0;
    491                 rootfs.service_id = 0;
     435                rootfs.devmap_handle = 0;
    492436        } else {
    493                
     437
    494438                /*
    495439                 * Unmounting a non-root file system.
     
    498442                 * file system, so we delegate the operation to it.
    499443                 */
    500                
     444
    501445                rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL);
     446                free(mp);
    502447                if (rc != EOK) {
    503448                        fibril_rwlock_write_unlock(&namespace_rwlock);
    504                         free(mp);
    505449                        vfs_node_put(mr_node);
    506450                        async_answer_0(rid, rc);
    507451                        return;
    508452                }
    509                
    510453                vfs_node_t *mp_node = vfs_node_get(&mp_res);
    511454                if (!mp_node) {
    512455                        fibril_rwlock_write_unlock(&namespace_rwlock);
    513                         free(mp);
    514456                        vfs_node_put(mr_node);
    515457                        async_answer_0(rid, ENOMEM);
    516458                        return;
    517459                }
    518                
    519                 exch = vfs_exchange_grab(mp_node->fs_handle);
    520                 rc = async_req_2_0(exch, VFS_OUT_UNMOUNT,
    521                     mp_node->service_id, mp_node->index);
    522                 vfs_exchange_release(exch);
    523                
     460
     461                phone = vfs_grab_phone(mp_node->fs_handle);
     462                rc = async_req_2_0(phone, VFS_OUT_UNMOUNT,
     463                    mp_node->devmap_handle, mp_node->index);
     464                vfs_release_phone(mp_node->fs_handle, phone);
    524465                if (rc != EOK) {
    525466                        fibril_rwlock_write_unlock(&namespace_rwlock);
    526                         free(mp);
    527467                        vfs_node_put(mp_node);
    528468                        vfs_node_put(mr_node);
     
    530470                        return;
    531471                }
    532                
     472
    533473                /* Drop the reference we got above. */
    534474                vfs_node_put(mp_node);
     
    536476                vfs_node_put(mp_node);
    537477        }
    538        
     478
     479
    539480        /*
    540481         * All went well, the mounted file system was successfully unmounted.
     
    542483         */
    543484        vfs_node_forget(mr_node);
     485
    544486        fibril_rwlock_write_unlock(&namespace_rwlock);
    545 
    546         fibril_mutex_lock(&mtab_list_lock);
    547 
    548         int found = 0;
    549 
    550         list_foreach(mtab_list, cur) {
    551                 mtab_ent_t *mtab_ent = list_get_instance(cur, mtab_ent_t,
    552                     link);
    553 
    554                 if (str_cmp(mtab_ent->mp, mp) == 0) {
    555                         list_remove(&mtab_ent->link);
    556                         mtab_size--;
    557                         free(mtab_ent);
    558                         found = 1;
    559                         break;
    560                 }
    561         }
    562         assert(found);
    563         fibril_mutex_unlock(&mtab_list_lock);
    564 
    565         free(mp);
    566 
    567487        async_answer_0(rid, EOK);
    568488}
     
    646566                if (node->size) {
    647567                        rc = vfs_truncate_internal(node->fs_handle,
    648                             node->service_id, node->index, 0);
     568                            node->devmap_handle, node->index, 0);
    649569                        if (rc) {
    650570                                fibril_rwlock_write_unlock(&node->contents_rwlock);
     
    689609}
    690610
     611void vfs_open_node(ipc_callid_t rid, ipc_call_t *request)
     612{
     613        // FIXME: check for sanity of the supplied fs, dev and index
     614       
     615        /*
     616         * The interface is open_node(fs, dev, index, oflag).
     617         */
     618        vfs_lookup_res_t lr;
     619       
     620        lr.triplet.fs_handle = IPC_GET_ARG1(*request);
     621        lr.triplet.devmap_handle = IPC_GET_ARG2(*request);
     622        lr.triplet.index = IPC_GET_ARG3(*request);
     623        int oflag = IPC_GET_ARG4(*request);
     624       
     625        fibril_rwlock_read_lock(&namespace_rwlock);
     626       
     627        int rc = vfs_open_node_internal(&lr);
     628        if (rc != EOK) {
     629                fibril_rwlock_read_unlock(&namespace_rwlock);
     630                async_answer_0(rid, rc);
     631                return;
     632        }
     633       
     634        vfs_node_t *node = vfs_node_get(&lr);
     635        fibril_rwlock_read_unlock(&namespace_rwlock);
     636       
     637        /* Truncate the file if requested and if necessary. */
     638        if (oflag & O_TRUNC) {
     639                fibril_rwlock_write_lock(&node->contents_rwlock);
     640                if (node->size) {
     641                        rc = vfs_truncate_internal(node->fs_handle,
     642                            node->devmap_handle, node->index, 0);
     643                        if (rc) {
     644                                fibril_rwlock_write_unlock(&node->contents_rwlock);
     645                                vfs_node_put(node);
     646                                async_answer_0(rid, rc);
     647                                return;
     648                        }
     649                        node->size = 0;
     650                }
     651                fibril_rwlock_write_unlock(&node->contents_rwlock);
     652        }
     653       
     654        /*
     655         * Get ourselves a file descriptor and the corresponding vfs_file_t
     656         * structure.
     657         */
     658        int fd = vfs_fd_alloc((oflag & O_DESC) != 0);
     659        if (fd < 0) {
     660                vfs_node_put(node);
     661                async_answer_0(rid, fd);
     662                return;
     663        }
     664        vfs_file_t *file = vfs_file_get(fd);
     665        file->node = node;
     666        if (oflag & O_APPEND)
     667                file->append = true;
     668       
     669        /*
     670         * The following increase in reference count is for the fact that the
     671         * file is being opened and that a file structure is pointing to it.
     672         * It is necessary so that the file will not disappear when
     673         * vfs_node_put() is called. The reference will be dropped by the
     674         * respective VFS_IN_CLOSE.
     675         */
     676        vfs_node_addref(node);
     677        vfs_node_put(node);
     678        vfs_file_put(file);
     679       
     680        /* Success! Return the new file descriptor to the client. */
     681        async_answer_1(rid, EOK, fd);
     682}
     683
    691684void vfs_sync(ipc_callid_t rid, ipc_call_t *request)
    692685{
     
    705698         */
    706699        fibril_mutex_lock(&file->lock);
    707         async_exch_t *fs_exch = vfs_exchange_grab(file->node->fs_handle);
     700        int fs_phone = vfs_grab_phone(file->node->fs_handle);
    708701       
    709702        /* Make a VFS_OUT_SYMC request at the destination FS server. */
    710703        aid_t msg;
    711704        ipc_call_t answer;
    712         msg = async_send_2(fs_exch, VFS_OUT_SYNC, file->node->service_id,
     705        msg = async_send_2(fs_phone, VFS_OUT_SYNC, file->node->devmap_handle,
    713706            file->node->index, &answer);
    714        
    715         vfs_exchange_release(fs_exch);
    716        
     707
    717708        /* Wait for reply from the FS server. */
    718709        sysarg_t rc;
    719710        async_wait_for(msg, &rc);
    720711       
     712        vfs_release_phone(file->node->fs_handle, fs_phone);
    721713        fibril_mutex_unlock(&file->lock);
    722        
     714
    723715        vfs_file_put(file);
    724716        async_answer_0(rid, rc);
    725717}
    726718
     719int vfs_close_internal(vfs_file_t *file)
     720{
     721        /*
     722         * Lock the open file structure so that no other thread can manipulate
     723         * the same open file at a time.
     724         */
     725        fibril_mutex_lock(&file->lock);
     726       
     727        if (file->refcnt <= 1) {
     728                /* Only close the file on the destination FS server
     729                   if there are no more file descriptors (except the
     730                   present one) pointing to this file. */
     731               
     732                int fs_phone = vfs_grab_phone(file->node->fs_handle);
     733               
     734                /* Make a VFS_OUT_CLOSE request at the destination FS server. */
     735                aid_t msg;
     736                ipc_call_t answer;
     737                msg = async_send_2(fs_phone, VFS_OUT_CLOSE,
     738                    file->node->devmap_handle, file->node->index, &answer);
     739               
     740                /* Wait for reply from the FS server. */
     741                sysarg_t rc;
     742                async_wait_for(msg, &rc);
     743               
     744                vfs_release_phone(file->node->fs_handle, fs_phone);
     745                fibril_mutex_unlock(&file->lock);
     746               
     747                return IPC_GET_ARG1(answer);
     748        }
     749       
     750        fibril_mutex_unlock(&file->lock);
     751        return EOK;
     752}
     753
    727754void vfs_close(ipc_callid_t rid, ipc_call_t *request)
    728755{
    729756        int fd = IPC_GET_ARG1(*request);
    730         int ret = vfs_fd_free(fd);
     757       
     758        /* Lookup the file structure corresponding to the file descriptor. */
     759        vfs_file_t *file = vfs_file_get(fd);
     760        if (!file) {
     761                async_answer_0(rid, ENOENT);
     762                return;
     763        }
     764       
     765        int ret = vfs_close_internal(file);
     766        if (ret != EOK)
     767                async_answer_0(rid, ret);
     768       
     769        vfs_file_put(file);
     770        ret = vfs_fd_free(fd);
    731771        async_answer_0(rid, ret);
    732772}
     
    734774static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read)
    735775{
     776        vfs_info_t *vi;
     777
    736778        /*
    737779         * The following code strongly depends on the fact that the files data
     
    743785         * open files supports parallel access!
    744786         */
    745        
     787
    746788        int fd = IPC_GET_ARG1(*request);
    747789       
     
    758800         */
    759801        fibril_mutex_lock(&file->lock);
    760        
    761         vfs_info_t *fs_info = fs_handle_to_info(file->node->fs_handle);
    762         assert(fs_info);
    763        
     802
     803        vi = fs_handle_to_info(file->node->fs_handle);
     804        assert(vi);
     805
    764806        /*
    765807         * Lock the file's node so that no other client can read/write to it at
     
    767809         * write implementation does not modify the file size.
    768810         */
    769         if ((read) ||
    770             ((fs_info->concurrent_read_write) && (fs_info->write_retains_size)))
     811        if (read || (vi->concurrent_read_write && vi->write_retains_size))
    771812                fibril_rwlock_read_lock(&file->node->contents_rwlock);
    772813        else
    773814                fibril_rwlock_write_lock(&file->node->contents_rwlock);
    774        
     815
    775816        if (file->node->type == VFS_NODE_DIRECTORY) {
    776817                /*
     
    782823        }
    783824       
    784         async_exch_t *fs_exch = vfs_exchange_grab(file->node->fs_handle);
     825        int fs_phone = vfs_grab_phone(file->node->fs_handle);
    785826       
    786827        /*
     
    794835        ipc_call_t answer;
    795836        if (read) {
    796                 rc = async_data_read_forward_4_1(fs_exch, VFS_OUT_READ,
    797                     file->node->service_id, file->node->index,
    798                     LOWER32(file->pos), UPPER32(file->pos), &answer);
     837                rc = async_data_read_forward_3_1(fs_phone, VFS_OUT_READ,
     838                    file->node->devmap_handle, file->node->index, file->pos,
     839                    &answer);
    799840        } else {
    800841                if (file->append)
    801842                        file->pos = file->node->size;
    802843               
    803                 rc = async_data_write_forward_4_1(fs_exch, VFS_OUT_WRITE,
    804                     file->node->service_id, file->node->index,
    805                     LOWER32(file->pos), UPPER32(file->pos), &answer);
    806         }
    807        
    808         vfs_exchange_release(fs_exch);
     844                rc = async_data_write_forward_3_1(fs_phone, VFS_OUT_WRITE,
     845                    file->node->devmap_handle, file->node->index, file->pos,
     846                    &answer);
     847        }
     848       
     849        vfs_release_phone(file->node->fs_handle, fs_phone);
    809850       
    810851        size_t bytes = IPC_GET_ARG1(answer);
     
    814855       
    815856        /* Unlock the VFS node. */
    816         if ((read) ||
    817             ((fs_info->concurrent_read_write) && (fs_info->write_retains_size)))
     857        if (read || (vi->concurrent_read_write && vi->write_retains_size))
    818858                fibril_rwlock_read_unlock(&file->node->contents_rwlock);
    819859        else {
    820860                /* Update the cached version of node's size. */
    821861                if (rc == EOK)
    822                         file->node->size = MERGE_LOUP32(IPC_GET_ARG2(answer),
    823                             IPC_GET_ARG3(answer));
     862                        file->node->size = IPC_GET_ARG2(answer);
    824863                fibril_rwlock_write_unlock(&file->node->contents_rwlock);
    825864        }
     
    933972}
    934973
    935 int vfs_truncate_internal(fs_handle_t fs_handle, service_id_t service_id,
     974int vfs_truncate_internal(fs_handle_t fs_handle, devmap_handle_t devmap_handle,
    936975    fs_index_t index, aoff64_t size)
    937976{
    938         async_exch_t *exch = vfs_exchange_grab(fs_handle);
    939         sysarg_t rc = async_req_4_0(exch, VFS_OUT_TRUNCATE,
    940             (sysarg_t) service_id, (sysarg_t) index, LOWER32(size),
    941             UPPER32(size));
    942         vfs_exchange_release(exch);
    943        
    944         return (int) rc;
     977        sysarg_t rc;
     978        int fs_phone;
     979       
     980        fs_phone = vfs_grab_phone(fs_handle);
     981        rc = async_req_4_0(fs_phone, VFS_OUT_TRUNCATE, (sysarg_t) devmap_handle,
     982            (sysarg_t) index, LOWER32(size), UPPER32(size));
     983        vfs_release_phone(fs_handle, fs_phone);
     984        return (int)rc;
    945985}
    946986
     
    9611001        fibril_rwlock_write_lock(&file->node->contents_rwlock);
    9621002        rc = vfs_truncate_internal(file->node->fs_handle,
    963             file->node->service_id, file->node->index, size);
     1003            file->node->devmap_handle, file->node->index, size);
    9641004        if (rc == EOK)
    9651005                file->node->size = size;
     
    9921032        fibril_mutex_lock(&file->lock);
    9931033
    994         async_exch_t *exch = vfs_exchange_grab(file->node->fs_handle);
     1034        int fs_phone = vfs_grab_phone(file->node->fs_handle);
    9951035       
    9961036        aid_t msg;
    997         msg = async_send_3(exch, VFS_OUT_STAT, file->node->service_id,
     1037        msg = async_send_3(fs_phone, VFS_OUT_STAT, file->node->devmap_handle,
    9981038            file->node->index, true, NULL);
    999         async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
    1000        
    1001         vfs_exchange_release(exch);
    1002        
     1039        async_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
    10031040        async_wait_for(msg, &rc);
    1004        
     1041        vfs_release_phone(file->node->fs_handle, fs_phone);
     1042
    10051043        fibril_mutex_unlock(&file->lock);
    10061044        vfs_file_put(file);
     
    10451083        fibril_rwlock_read_unlock(&namespace_rwlock);
    10461084
    1047         async_exch_t *exch = vfs_exchange_grab(node->fs_handle);
    1048        
     1085        int fs_phone = vfs_grab_phone(node->fs_handle);
    10491086        aid_t msg;
    1050         msg = async_send_3(exch, VFS_OUT_STAT, node->service_id,
     1087        msg = async_send_3(fs_phone, VFS_OUT_STAT, node->devmap_handle,
    10511088            node->index, false, NULL);
    1052         async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
    1053        
    1054         vfs_exchange_release(exch);
     1089        async_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
    10551090       
    10561091        sysarg_t rv;
    10571092        async_wait_for(msg, &rv);
     1093        vfs_release_phone(node->fs_handle, fs_phone);
    10581094
    10591095        async_answer_0(rid, rv);
     
    12251261        /* Check whether linking to the same file system instance. */
    12261262        if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) ||
    1227             (old_node->service_id != new_par_lr.triplet.service_id)) {
     1263            (old_node->devmap_handle != new_par_lr.triplet.devmap_handle)) {
    12281264                fibril_rwlock_write_unlock(&namespace_rwlock);
    12291265                vfs_node_put(old_node);
     
    13331369        fibril_mutex_lock(&oldfile->lock);
    13341370       
    1335         /* Make sure newfd is closed. */
    1336         (void) vfs_fd_free(newfd);
     1371        /* Lookup an open file structure possibly corresponding to newfd. */
     1372        vfs_file_t *newfile = vfs_file_get(newfd);
     1373        if (newfile) {
     1374                /* Close the originally opened file. */
     1375                int ret = vfs_close_internal(newfile);
     1376                if (ret != EOK) {
     1377                        fibril_mutex_unlock(&oldfile->lock);
     1378                        vfs_file_put(oldfile);
     1379                        vfs_file_put(newfile);
     1380                        async_answer_0(rid, ret);
     1381                        return;
     1382                }
     1383               
     1384                ret = vfs_fd_free(newfd);
     1385                if (ret != EOK) {
     1386                        fibril_mutex_unlock(&oldfile->lock);
     1387                        vfs_file_put(oldfile);
     1388                        vfs_file_put(newfile);
     1389                        async_answer_0(rid, ret);
     1390                        return;
     1391                }
     1392                vfs_file_put(newfile);
     1393        }
    13371394       
    13381395        /* Assign the old file to newfd. */
     
    13471404}
    13481405
    1349 void vfs_wait_handle(ipc_callid_t rid, ipc_call_t *request)
    1350 {
    1351         int fd = vfs_wait_handle_internal();
    1352         async_answer_1(rid, EOK, fd);
    1353 }
    1354 
    1355 void vfs_get_mtab(ipc_callid_t rid, ipc_call_t *request)
    1356 {
    1357         ipc_callid_t callid;
    1358         ipc_call_t data;
    1359         sysarg_t rc = EOK;
    1360         size_t len;
    1361 
    1362         fibril_mutex_lock(&mtab_list_lock);
    1363 
    1364         /* Send to the caller the number of mounted filesystems */
    1365         callid = async_get_call(&data);
    1366         if (IPC_GET_IMETHOD(data) != VFS_IN_PING) {
    1367                 rc = ENOTSUP;
    1368                 async_answer_0(callid, rc);
    1369                 goto exit;
    1370         }
    1371         async_answer_1(callid, EOK, mtab_size);
    1372 
    1373         list_foreach(mtab_list, cur) {
    1374                 mtab_ent_t *mtab_ent = list_get_instance(cur, mtab_ent_t,
    1375                     link);
    1376 
    1377                 rc = ENOTSUP;
    1378 
    1379                 if (!async_data_read_receive(&callid, &len)) {
    1380                         async_answer_0(callid, rc);
    1381                         goto exit;
    1382                 }
    1383 
    1384                 (void) async_data_read_finalize(callid, mtab_ent->mp,
    1385                     str_size(mtab_ent->mp));
    1386 
    1387                 if (!async_data_read_receive(&callid, &len)) {
    1388                         async_answer_0(callid, rc);
    1389                         goto exit;
    1390                 }
    1391 
    1392                 (void) async_data_read_finalize(callid, mtab_ent->opts,
    1393                     str_size(mtab_ent->opts));
    1394 
    1395                 if (!async_data_read_receive(&callid, &len)) {
    1396                         async_answer_0(callid, rc);
    1397                         goto exit;
    1398                 }
    1399 
    1400                 (void) async_data_read_finalize(callid, mtab_ent->fs_name,
    1401                     str_size(mtab_ent->fs_name));
    1402 
    1403                 callid = async_get_call(&data);
    1404 
    1405                 if (IPC_GET_IMETHOD(data) != VFS_IN_PING) {
    1406                         async_answer_0(callid, rc);
    1407                         goto exit;
    1408                 }
    1409 
    1410                 rc = EOK;
    1411                 async_answer_2(callid, rc, mtab_ent->instance,
    1412                     mtab_ent->service_id);
    1413         }
    1414 
    1415 exit:
    1416         fibril_mutex_unlock(&mtab_list_lock);
    1417         async_answer_0(rid, rc);
    1418 }
    1419 
    14201406/**
    14211407 * @}
Note: See TracChangeset for help on using the changeset viewer.