Ignore:
File:
1 edited

Legend:

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

    rdd2cfa7 rffa2c8ef  
    3737
    3838#include "vfs.h"
    39 #include <ipc/ipc.h>
     39#include <macros.h>
     40#include <stdint.h>
    4041#include <async.h>
    4142#include <errno.h>
    4243#include <stdio.h>
    4344#include <stdlib.h>
    44 #include <string.h>
     45#include <str.h>
    4546#include <bool.h>
    46 #include <fibril_sync.h>
     47#include <fibril_synch.h>
    4748#include <adt/list.h>
    4849#include <unistd.h>
     
    5354
    5455/* Forward declarations of static functions. */
    55 static int vfs_truncate_internal(fs_handle_t, dev_handle_t, fs_index_t, size_t);
     56static int vfs_truncate_internal(fs_handle_t, devmap_handle_t, fs_index_t,
     57    aoff64_t);
    5658
    5759/**
     
    6365vfs_pair_t rootfs = {
    6466        .fs_handle = 0,
    65         .dev_handle = 0
     67        .devmap_handle = 0
    6668};
    6769
    68 static void vfs_mount_internal(ipc_callid_t rid, dev_handle_t dev_handle,
     70static void vfs_mount_internal(ipc_callid_t rid, devmap_handle_t devmap_handle,
    6971    fs_handle_t fs_handle, char *mp, char *opts)
    7072{
     
    7678        size_t rsize;
    7779        unsigned rlnkcnt;
    78         ipcarg_t rc;
     80        sysarg_t rc;
    7981        int phone;
    8082        aid_t msg;
     
    8890                        /* Trying to mount root FS over root FS */
    8991                        fibril_rwlock_write_unlock(&namespace_rwlock);
    90                         ipc_answer_0(rid, EBUSY);
    91                         return;
    92                 }
    93                
    94                 rc = vfs_lookup_internal(mp, L_DIRECTORY, &mp_res, NULL);
     92                        async_answer_0(rid, EBUSY);
     93                        return;
     94                }
     95               
     96                rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL);
    9597                if (rc != EOK) {
    9698                        /* The lookup failed for some reason. */
    9799                        fibril_rwlock_write_unlock(&namespace_rwlock);
    98                         ipc_answer_0(rid, rc);
     100                        async_answer_0(rid, rc);
    99101                        return;
    100102                }
     
    103105                if (!mp_node) {
    104106                        fibril_rwlock_write_unlock(&namespace_rwlock);
    105                         ipc_answer_0(rid, ENOMEM);
     107                        async_answer_0(rid, ENOMEM);
    106108                        return;
    107109                }
     
    123125                        phone = vfs_grab_phone(fs_handle);
    124126                        msg = async_send_1(phone, VFS_OUT_MOUNTED,
    125                             (ipcarg_t) dev_handle, &answer);
     127                            (sysarg_t) devmap_handle, &answer);
    126128                        /* send the mount options */
    127                         rc = ipc_data_write_start(phone, (void *)opts,
     129                        rc = async_data_write_start(phone, (void *)opts,
    128130                            str_size(opts));
    129131                        if (rc != EOK) {
    130132                                async_wait_for(msg, NULL);
    131                                 vfs_release_phone(phone);
     133                                vfs_release_phone(fs_handle, phone);
    132134                                fibril_rwlock_write_unlock(&namespace_rwlock);
    133                                 ipc_answer_0(rid, rc);
     135                                async_answer_0(rid, rc);
    134136                                return;
    135137                        }
    136138                        async_wait_for(msg, &rc);
    137                         vfs_release_phone(phone);
     139                        vfs_release_phone(fs_handle, phone);
    138140                       
    139141                        if (rc != EOK) {
    140142                                fibril_rwlock_write_unlock(&namespace_rwlock);
    141                                 ipc_answer_0(rid, rc);
     143                                async_answer_0(rid, rc);
    142144                                return;
    143145                        }
     
    148150                       
    149151                        mr_res.triplet.fs_handle = fs_handle;
    150                         mr_res.triplet.dev_handle = dev_handle;
     152                        mr_res.triplet.devmap_handle = devmap_handle;
    151153                        mr_res.triplet.index = rindex;
    152154                        mr_res.size = rsize;
     
    155157                       
    156158                        rootfs.fs_handle = fs_handle;
    157                         rootfs.dev_handle = dev_handle;
     159                        rootfs.devmap_handle = devmap_handle;
    158160                       
    159161                        /* Add reference to the mounted root. */
     
    162164                       
    163165                        fibril_rwlock_write_unlock(&namespace_rwlock);
    164                         ipc_answer_0(rid, rc);
     166                        async_answer_0(rid, rc);
    165167                        return;
    166168                } else {
     
    170172                         */
    171173                        fibril_rwlock_write_unlock(&namespace_rwlock);
    172                         ipc_answer_0(rid, ENOENT);
     174                        async_answer_0(rid, ENOENT);
    173175                        return;
    174176                }
     
    185187        phone = vfs_grab_phone(mp_res.triplet.fs_handle);
    186188        msg = async_send_4(phone, VFS_OUT_MOUNT,
    187             (ipcarg_t) mp_res.triplet.dev_handle,
    188             (ipcarg_t) mp_res.triplet.index,
    189             (ipcarg_t) fs_handle,
    190             (ipcarg_t) dev_handle, &answer);
     189            (sysarg_t) mp_res.triplet.devmap_handle,
     190            (sysarg_t) mp_res.triplet.index,
     191            (sysarg_t) fs_handle,
     192            (sysarg_t) devmap_handle, &answer);
    191193       
    192194        /* send connection */
     
    194196        if (rc != EOK) {
    195197                async_wait_for(msg, NULL);
    196                 vfs_release_phone(mountee_phone);
    197                 vfs_release_phone(phone);
     198                vfs_release_phone(fs_handle, mountee_phone);
     199                vfs_release_phone(mp_res.triplet.fs_handle, phone);
    198200                /* Mount failed, drop reference to mp_node. */
    199201                if (mp_node)
    200202                        vfs_node_put(mp_node);
    201                 ipc_answer_0(rid, rc);
     203                async_answer_0(rid, rc);
    202204                fibril_rwlock_write_unlock(&namespace_rwlock);
    203205                return;
    204206        }
    205207
    206         vfs_release_phone(mountee_phone);
     208        vfs_release_phone(fs_handle, mountee_phone);
    207209       
    208210        /* send the mount options */
    209         rc = ipc_data_write_start(phone, (void *)opts, str_size(opts));
     211        rc = async_data_write_start(phone, (void *)opts, str_size(opts));
    210212        if (rc != EOK) {
    211213                async_wait_for(msg, NULL);
    212                 vfs_release_phone(phone);
     214                vfs_release_phone(mp_res.triplet.fs_handle, phone);
    213215                /* Mount failed, drop reference to mp_node. */
    214216                if (mp_node)
    215217                        vfs_node_put(mp_node);
    216218                fibril_rwlock_write_unlock(&namespace_rwlock);
    217                 ipc_answer_0(rid, rc);
     219                async_answer_0(rid, rc);
    218220                return;
    219221        }
    220222        async_wait_for(msg, &rc);
    221         vfs_release_phone(phone);
     223        vfs_release_phone(mp_res.triplet.fs_handle, phone);
    222224       
    223225        if (rc == EOK) {
     
    227229       
    228230                mr_res.triplet.fs_handle = fs_handle;
    229                 mr_res.triplet.dev_handle = dev_handle;
     231                mr_res.triplet.devmap_handle = devmap_handle;
    230232                mr_res.triplet.index = rindex;
    231233                mr_res.size = rsize;
     
    242244        }
    243245
    244         ipc_answer_0(rid, rc);
     246        async_answer_0(rid, rc);
    245247        fibril_rwlock_write_unlock(&namespace_rwlock);
    246248}
     
    248250void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
    249251{
     252        devmap_handle_t devmap_handle;
     253
    250254        /*
    251255         * We expect the library to do the device-name to device-handle
     
    253257         * in the request.
    254258         */
    255         dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
     259        devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    256260       
    257261        /*
     
    266270       
    267271        /* We want the client to send us the mount point. */
    268         ipc_callid_t callid;
    269         size_t size;
    270         if (!ipc_data_write_receive(&callid, &size)) {
    271                 ipc_answer_0(callid, EINVAL);
    272                 ipc_answer_0(rid, EINVAL);
    273                 return;
    274         }
    275        
    276         /* Check whether size is reasonable wrt. the mount point. */
    277         if ((size < 1) || (size > MAX_PATH_LEN)) {
    278                 ipc_answer_0(callid, EINVAL);
    279                 ipc_answer_0(rid, EINVAL);
    280                 return;
    281         }
    282        
    283         /* Allocate buffer for the mount point data being received. */
    284         char *mp = malloc(size + 1);
    285         if (!mp) {
    286                 ipc_answer_0(callid, ENOMEM);
    287                 ipc_answer_0(rid, ENOMEM);
    288                 return;
    289         }
    290        
    291         /* Deliver the mount point. */
    292         ipcarg_t retval = ipc_data_write_finalize(callid, mp, size);
    293         if (retval != EOK) {
    294                 ipc_answer_0(rid, retval);
     272        char *mp;
     273        int rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN,
     274            0, NULL);
     275        if (rc != EOK) {
     276                async_answer_0(rid, rc);
     277                return;
     278        }
     279       
     280        /* Now we expect to receive the mount options. */
     281        char *opts;
     282        rc = async_data_write_accept((void **) &opts, true, 0, MAX_MNTOPTS_LEN,
     283            0, NULL);
     284        if (rc != EOK) {
    295285                free(mp);
    296                 return;
    297         }
    298         mp[size] = '\0';
    299        
    300         /* Now we expect to receive the mount options. */
    301         if (!ipc_data_write_receive(&callid, &size)) {
    302                 ipc_answer_0(callid, EINVAL);
    303                 ipc_answer_0(rid, EINVAL);
    304                 free(mp);
    305                 return;
    306         }
    307 
    308         /* Check the offered options size. */
    309         if (size > MAX_MNTOPTS_LEN) {
    310                 ipc_answer_0(callid, EINVAL);
    311                 ipc_answer_0(rid, EINVAL);
    312                 free(mp);
    313                 return;
    314         }
    315 
    316         /* Allocate buffer for the mount options. */
    317         char *opts = (char *) malloc(size + 1);
    318         if (!opts) {
    319                 ipc_answer_0(callid, ENOMEM);
    320                 ipc_answer_0(rid, ENOMEM);
    321                 free(mp);
    322                 return;
    323         }
    324 
    325         /* Deliver the mount options. */
    326         retval = ipc_data_write_finalize(callid, opts, size);
    327         if (retval != EOK) {
    328                 ipc_answer_0(rid, retval);
     286                async_answer_0(rid, rc);
     287                return;
     288        }
     289       
     290        /*
     291         * Now, we expect the client to send us data with the name of the file
     292         * system.
     293         */
     294        char *fs_name;
     295        rc = async_data_write_accept((void **) &fs_name, true, 0,
     296            FS_NAME_MAXLEN, 0, NULL);
     297        if (rc != EOK) {
    329298                free(mp);
    330299                free(opts);
    331                 return;
    332         }
    333         opts[size] = '\0';
    334        
    335         /*
    336          * Now, we expect the client to send us data with the name of the file
    337          * system.
    338          */
    339         if (!ipc_data_write_receive(&callid, &size)) {
    340                 ipc_answer_0(callid, EINVAL);
    341                 ipc_answer_0(rid, EINVAL);
    342                 free(mp);
    343                 free(opts);
    344                 return;
    345         }
    346        
    347         /*
    348          * Don't receive more than is necessary for storing a full file system
    349          * name.
    350          */
    351         if ((size < 1) || (size > FS_NAME_MAXLEN)) {
    352                 ipc_answer_0(callid, EINVAL);
    353                 ipc_answer_0(rid, EINVAL);
    354                 free(mp);
    355                 free(opts);
    356                 return;
    357         }
    358        
    359         /*
    360          * Allocate buffer for file system name.
    361          */
    362         char *fs_name = (char *) malloc(size + 1);
    363         if (fs_name == NULL) {
    364                 ipc_answer_0(callid, ENOMEM);
    365                 ipc_answer_0(rid, ENOMEM);
    366                 free(mp);
    367                 free(opts);
    368                 return;
    369         }
    370        
    371         /* Deliver the file system name. */
    372         retval = ipc_data_write_finalize(callid, fs_name, size);
    373         if (retval != EOK) {
    374                 ipc_answer_0(rid, retval);
    375                 free(mp);
    376                 free(opts);
    377                 free(fs_name);
    378                 return;
    379         }
    380         fs_name[size] = '\0';
    381 
     300                async_answer_0(rid, rc);
     301                return;
     302        }
     303       
    382304        /*
    383305         * Wait for IPC_M_PING so that we can return an error if we don't know
     
    385307         */
    386308        ipc_call_t data;
    387         callid = async_get_call(&data);
    388         if (IPC_GET_METHOD(data) != IPC_M_PING) {
    389                 ipc_answer_0(callid, ENOTSUP);
    390                 ipc_answer_0(rid, ENOTSUP);
     309        ipc_callid_t callid = async_get_call(&data);
     310        if (IPC_GET_IMETHOD(data) != IPC_M_PING) {
     311                async_answer_0(callid, ENOTSUP);
     312                async_answer_0(rid, ENOTSUP);
    391313                free(mp);
    392314                free(opts);
     
    410332               
    411333                fibril_mutex_unlock(&fs_head_lock);
    412                 ipc_answer_0(callid, ENOENT);
    413                 ipc_answer_0(rid, ENOENT);
     334                async_answer_0(callid, ENOENT);
     335                async_answer_0(rid, ENOENT);
    414336                free(mp);
    415337                free(fs_name);
     
    420342       
    421343        /* Acknowledge that we know fs_name. */
    422         ipc_answer_0(callid, EOK);
     344        async_answer_0(callid, EOK);
    423345       
    424346        /* Do the mount */
    425         vfs_mount_internal(rid, dev_handle, fs_handle, mp, opts);
     347        vfs_mount_internal(rid, devmap_handle, fs_handle, mp, opts);
    426348        free(mp);
    427349        free(fs_name);
     
    429351}
    430352
     353void vfs_unmount(ipc_callid_t rid, ipc_call_t *request)
     354{
     355        int rc;
     356        char *mp;
     357        vfs_lookup_res_t mp_res;
     358        vfs_lookup_res_t mr_res;
     359        vfs_node_t *mr_node;
     360        int phone;
     361
     362        /*
     363         * Receive the mount point path.
     364         */
     365        rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN,
     366            0, NULL);
     367        if (rc != EOK)
     368                async_answer_0(rid, rc);
     369
     370        /*
     371         * Taking the namespace lock will do two things for us. First, it will
     372         * prevent races with other lookup operations. Second, it will stop new
     373         * references to already existing VFS nodes and creation of new VFS
     374         * nodes. This is because new references are added as a result of some
     375         * lookup operation or at least of some operation which is protected by
     376         * the namespace lock.
     377         */
     378        fibril_rwlock_write_lock(&namespace_rwlock);
     379       
     380        /*
     381         * Lookup the mounted root and instantiate it.
     382         */
     383        rc = vfs_lookup_internal(mp, L_ROOT, &mr_res, NULL);
     384        if (rc != EOK) {
     385                fibril_rwlock_write_unlock(&namespace_rwlock);
     386                free(mp);
     387                async_answer_0(rid, rc);
     388                return;
     389        }
     390        mr_node = vfs_node_get(&mr_res);
     391        if (!mr_node) {
     392                fibril_rwlock_write_unlock(&namespace_rwlock);
     393                free(mp);
     394                async_answer_0(rid, ENOMEM);
     395                return;
     396        }
     397
     398        /*
     399         * Count the total number of references for the mounted file system. We
     400         * are expecting at least two. One which we got above and one which we
     401         * got when the file system was mounted. If we find more, it means that
     402         * the file system cannot be gracefully unmounted at the moment because
     403         * someone is working with it.
     404         */
     405        if (vfs_nodes_refcount_sum_get(mr_node->fs_handle,
     406            mr_node->devmap_handle) != 2) {
     407                fibril_rwlock_write_unlock(&namespace_rwlock);
     408                vfs_node_put(mr_node);
     409                free(mp);
     410                async_answer_0(rid, EBUSY);
     411                return;
     412        }
     413
     414        if (str_cmp(mp, "/") == 0) {
     415
     416                /*
     417                 * Unmounting the root file system.
     418                 *
     419                 * In this case, there is no mount point node and we send
     420                 * VFS_OUT_UNMOUNTED directly to the mounted file system.
     421                 */
     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);
     428                if (rc != EOK) {
     429                        fibril_rwlock_write_unlock(&namespace_rwlock);
     430                        vfs_node_put(mr_node);
     431                        async_answer_0(rid, rc);
     432                        return;
     433                }
     434                rootfs.fs_handle = 0;
     435                rootfs.devmap_handle = 0;
     436        } else {
     437
     438                /*
     439                 * Unmounting a non-root file system.
     440                 *
     441                 * We have a regular mount point node representing the parent
     442                 * file system, so we delegate the operation to it.
     443                 */
     444
     445                rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL);
     446                free(mp);
     447                if (rc != EOK) {
     448                        fibril_rwlock_write_unlock(&namespace_rwlock);
     449                        vfs_node_put(mr_node);
     450                        async_answer_0(rid, rc);
     451                        return;
     452                }
     453                vfs_node_t *mp_node = vfs_node_get(&mp_res);
     454                if (!mp_node) {
     455                        fibril_rwlock_write_unlock(&namespace_rwlock);
     456                        vfs_node_put(mr_node);
     457                        async_answer_0(rid, ENOMEM);
     458                        return;
     459                }
     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);
     465                if (rc != EOK) {
     466                        fibril_rwlock_write_unlock(&namespace_rwlock);
     467                        vfs_node_put(mp_node);
     468                        vfs_node_put(mr_node);
     469                        async_answer_0(rid, rc);
     470                        return;
     471                }
     472
     473                /* Drop the reference we got above. */
     474                vfs_node_put(mp_node);
     475                /* Drop the reference from when the file system was mounted. */
     476                vfs_node_put(mp_node);
     477        }
     478
     479
     480        /*
     481         * All went well, the mounted file system was successfully unmounted.
     482         * The only thing left is to forget the unmounted root VFS node.
     483         */
     484        vfs_node_forget(mr_node);
     485
     486        fibril_rwlock_write_unlock(&namespace_rwlock);
     487        async_answer_0(rid, EOK);
     488}
     489
    431490void vfs_open(ipc_callid_t rid, ipc_call_t *request)
    432491{
    433         if (!vfs_files_init()) {
    434                 ipc_answer_0(rid, ENOMEM);
    435                 return;
    436         }
    437        
    438492        /*
    439493         * The POSIX interface is open(path, oflag, mode).
     
    447501        int oflag = IPC_GET_ARG2(*request);
    448502        int mode = IPC_GET_ARG3(*request);
    449         size_t len;
    450503
    451504        /* Ignore mode for now. */
     
    454507        /*
    455508         * 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.
     509         * L_DIRECTORY. Make sure that the user does not pass L_OPEN,
     510         * L_ROOT or L_MP.
    457511         */
    458512        if (((lflag & (L_FILE | L_DIRECTORY)) == 0) ||
    459513            ((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) ||
    460             ((lflag & L_OPEN) != 0)) {
    461                 ipc_answer_0(rid, EINVAL);
     514            (lflag & (L_OPEN | L_ROOT | L_MP))) {
     515                async_answer_0(rid, EINVAL);
    462516                return;
    463517        }
     
    468522                lflag |= L_EXCLUSIVE;
    469523       
    470         ipc_callid_t callid;
    471         if (!ipc_data_write_receive(&callid, &len)) {
    472                 ipc_answer_0(callid, EINVAL);
    473                 ipc_answer_0(rid, EINVAL);
    474                 return;
    475         }
    476        
    477         char *path = malloc(len + 1);
    478         if (!path) {
    479                 ipc_answer_0(callid, ENOMEM);
    480                 ipc_answer_0(rid, ENOMEM);
    481                 return;
    482         }
    483        
    484         int rc;
    485         if ((rc = ipc_data_write_finalize(callid, path, len))) {
    486                 ipc_answer_0(rid, rc);
    487                 free(path);
    488                 return;
    489         }
    490         path[len] = '\0';
     524        char *path;
     525        int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
     526        if (rc != EOK) {
     527                async_answer_0(rid, rc);
     528                return;
     529        }
    491530       
    492531        /*
     
    508547                else
    509548                        fibril_rwlock_read_unlock(&namespace_rwlock);
    510                 ipc_answer_0(rid, rc);
     549                async_answer_0(rid, rc);
    511550                free(path);
    512551                return;
     
    527566                if (node->size) {
    528567                        rc = vfs_truncate_internal(node->fs_handle,
    529                             node->dev_handle, node->index, 0);
     568                            node->devmap_handle, node->index, 0);
    530569                        if (rc) {
    531570                                fibril_rwlock_write_unlock(&node->contents_rwlock);
    532571                                vfs_node_put(node);
    533                                 ipc_answer_0(rid, rc);
     572                                async_answer_0(rid, rc);
    534573                                return;
    535574                        }
     
    543582         * structure.
    544583         */
    545         int fd = vfs_fd_alloc();
     584        int fd = vfs_fd_alloc((oflag & O_DESC) != 0);
    546585        if (fd < 0) {
    547586                vfs_node_put(node);
    548                 ipc_answer_0(rid, fd);
     587                async_answer_0(rid, fd);
    549588                return;
    550589        }
    551590        vfs_file_t *file = vfs_file_get(fd);
     591        assert(file);
    552592        file->node = node;
    553593        if (oflag & O_APPEND)
     
    563603        vfs_node_addref(node);
    564604        vfs_node_put(node);
     605        vfs_file_put(file);
    565606       
    566607        /* Success! Return the new file descriptor to the client. */
    567         ipc_answer_1(rid, EOK, fd);
     608        async_answer_1(rid, EOK, fd);
    568609}
    569610
     
    572613        // FIXME: check for sanity of the supplied fs, dev and index
    573614       
    574         if (!vfs_files_init()) {
    575                 ipc_answer_0(rid, ENOMEM);
    576                 return;
    577         }
    578        
    579615        /*
    580616         * The interface is open_node(fs, dev, index, oflag).
     
    583619       
    584620        lr.triplet.fs_handle = IPC_GET_ARG1(*request);
    585         lr.triplet.dev_handle = IPC_GET_ARG2(*request);
     621        lr.triplet.devmap_handle = IPC_GET_ARG2(*request);
    586622        lr.triplet.index = IPC_GET_ARG3(*request);
    587623        int oflag = IPC_GET_ARG4(*request);
     
    592628        if (rc != EOK) {
    593629                fibril_rwlock_read_unlock(&namespace_rwlock);
    594                 ipc_answer_0(rid, rc);
     630                async_answer_0(rid, rc);
    595631                return;
    596632        }
     
    604640                if (node->size) {
    605641                        rc = vfs_truncate_internal(node->fs_handle,
    606                             node->dev_handle, node->index, 0);
     642                            node->devmap_handle, node->index, 0);
    607643                        if (rc) {
    608644                                fibril_rwlock_write_unlock(&node->contents_rwlock);
    609645                                vfs_node_put(node);
    610                                 ipc_answer_0(rid, rc);
     646                                async_answer_0(rid, rc);
    611647                                return;
    612648                        }
     
    620656         * structure.
    621657         */
    622         int fd = vfs_fd_alloc();
     658        int fd = vfs_fd_alloc((oflag & O_DESC) != 0);
    623659        if (fd < 0) {
    624660                vfs_node_put(node);
    625                 ipc_answer_0(rid, fd);
     661                async_answer_0(rid, fd);
    626662                return;
    627663        }
     
    640676        vfs_node_addref(node);
    641677        vfs_node_put(node);
     678        vfs_file_put(file);
    642679       
    643680        /* Success! Return the new file descriptor to the client. */
    644         ipc_answer_1(rid, EOK, fd);
     681        async_answer_1(rid, EOK, fd);
    645682}
    646683
     
    652689        vfs_file_t *file = vfs_file_get(fd);
    653690        if (!file) {
    654                 ipc_answer_0(rid, ENOENT);
     691                async_answer_0(rid, ENOENT);
    655692                return;
    656693        }
     
    666703        aid_t msg;
    667704        ipc_call_t answer;
    668         msg = async_send_2(fs_phone, VFS_OUT_SYNC, file->node->dev_handle,
     705        msg = async_send_2(fs_phone, VFS_OUT_SYNC, file->node->devmap_handle,
    669706            file->node->index, &answer);
    670707
    671708        /* Wait for reply from the FS server. */
    672         ipcarg_t rc;
     709        sysarg_t rc;
    673710        async_wait_for(msg, &rc);
    674711       
    675         vfs_release_phone(fs_phone);
     712        vfs_release_phone(file->node->fs_handle, fs_phone);
    676713        fibril_mutex_unlock(&file->lock);
    677        
    678         ipc_answer_0(rid, rc);
     714
     715        vfs_file_put(file);
     716        async_answer_0(rid, rc);
     717}
     718
     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;
    679752}
    680753
     
    686759        vfs_file_t *file = vfs_file_get(fd);
    687760        if (!file) {
    688                 ipc_answer_0(rid, ENOENT);
    689                 return;
    690         }
    691        
    692         /*
    693          * Lock the open file structure so that no other thread can manipulate
    694          * the same open file at a time.
    695          */
    696         fibril_mutex_lock(&file->lock);
    697         int fs_phone = vfs_grab_phone(file->node->fs_handle);
    698        
    699         /* Make a VFS_OUT_CLOSE request at the destination FS server. */
    700         aid_t msg;
    701         ipc_call_t answer;
    702         msg = async_send_2(fs_phone, VFS_OUT_CLOSE, file->node->dev_handle,
    703             file->node->index, &answer);
    704 
    705         /* Wait for reply from the FS server. */
    706         ipcarg_t rc;
    707         async_wait_for(msg, &rc);
    708 
    709         vfs_release_phone(fs_phone);
    710         fibril_mutex_unlock(&file->lock);
    711        
    712         int retval = IPC_GET_ARG1(answer);
    713         if (retval != EOK)
    714                 ipc_answer_0(rid, retval);
    715        
    716         retval = vfs_fd_free(fd);
    717         ipc_answer_0(rid, retval);
     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);
     771        async_answer_0(rid, ret);
    718772}
    719773
    720774static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read)
    721775{
     776        vfs_info_t *vi;
    722777
    723778        /*
     
    736791        vfs_file_t *file = vfs_file_get(fd);
    737792        if (!file) {
    738                 ipc_answer_0(rid, ENOENT);
    739                 return;
    740         }
    741        
    742         /*
    743          * Now we need to receive a call with client's
    744          * IPC_M_DATA_READ/IPC_M_DATA_WRITE request.
    745          */
    746         ipc_callid_t callid;
    747         int res;
    748         if (read)
    749                 res = ipc_data_read_receive(&callid, NULL);
    750         else
    751                 res = ipc_data_write_receive(&callid, NULL);
    752         if (!res) {
    753                 ipc_answer_0(callid, EINVAL);
    754                 ipc_answer_0(rid, EINVAL);
     793                async_answer_0(rid, ENOENT);
    755794                return;
    756795        }
     
    762801        fibril_mutex_lock(&file->lock);
    763802
     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
    766          * the same time.
    767          */
    768         if (read)
     808         * the same time unless the FS supports concurrent reads/writes and its
     809         * write implementation does not modify the file size.
     810         */
     811        if (read || (vi->concurrent_read_write && vi->write_retains_size))
    769812                fibril_rwlock_read_lock(&file->node->contents_rwlock);
    770813        else
     
    780823        }
    781824       
    782         int fs_phone = vfs_grab_phone(file->node->fs_handle);   
    783        
    784         /* Make a VFS_READ/VFS_WRITE request at the destination FS server. */
    785         aid_t msg;
    786         ipc_call_t answer;
    787         if (!read && file->append)
    788                 file->pos = file->node->size;
    789         msg = async_send_3(fs_phone, read ? VFS_OUT_READ : VFS_OUT_WRITE,
    790             file->node->dev_handle, file->node->index, file->pos, &answer);
    791        
    792         /*
    793          * Forward the IPC_M_DATA_READ/IPC_M_DATA_WRITE request to the
     825        int fs_phone = vfs_grab_phone(file->node->fs_handle);
     826       
     827        /*
     828         * Make a VFS_READ/VFS_WRITE request at the destination FS server
     829         * and forward the IPC_M_DATA_READ/IPC_M_DATA_WRITE request to the
    794830         * destination FS server. The call will be routed as if sent by
    795831         * ourselves. Note that call arguments are immutable in this case so we
    796832         * don't have to bother.
    797833         */
    798         ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
    799 
    800         /* Wait for reply from the FS server. */
    801         ipcarg_t rc;
    802         async_wait_for(msg, &rc);
    803        
    804         vfs_release_phone(fs_phone);
     834        sysarg_t rc;
     835        ipc_call_t answer;
     836        if (read) {
     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);
     840        } else {
     841                if (file->append)
     842                        file->pos = file->node->size;
     843               
     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);
    805850       
    806851        size_t bytes = IPC_GET_ARG1(answer);
    807 
     852       
    808853        if (file->node->type == VFS_NODE_DIRECTORY)
    809854                fibril_rwlock_read_unlock(&namespace_rwlock);
    810855       
    811856        /* Unlock the VFS node. */
    812         if (read)
     857        if (read || (vi->concurrent_read_write && vi->write_retains_size))
    813858                fibril_rwlock_read_unlock(&file->node->contents_rwlock);
    814859        else {
     
    823868                file->pos += bytes;
    824869        fibril_mutex_unlock(&file->lock);
    825        
     870        vfs_file_put(file);     
     871
    826872        /*
    827873         * FS server's reply is the final result of the whole operation we
    828874         * return to the client.
    829875         */
    830         ipc_answer_1(rid, rc, bytes);
     876        async_answer_1(rid, rc, bytes);
    831877}
    832878
     
    844890{
    845891        int fd = (int) IPC_GET_ARG1(*request);
    846         off_t off = (off_t) IPC_GET_ARG2(*request);
    847         int whence = (int) IPC_GET_ARG3(*request);
    848 
    849 
     892        off64_t off = (off64_t) MERGE_LOUP32(IPC_GET_ARG2(*request),
     893            IPC_GET_ARG3(*request));
     894        int whence = (int) IPC_GET_ARG4(*request);
     895       
    850896        /* Lookup the file structure corresponding to the file descriptor. */
    851897        vfs_file_t *file = vfs_file_get(fd);
    852898        if (!file) {
    853                 ipc_answer_0(rid, ENOENT);
    854                 return;
    855         }
    856 
    857         off_t newpos;
     899                async_answer_0(rid, ENOENT);
     900                return;
     901        }
     902       
    858903        fibril_mutex_lock(&file->lock);
    859         if (whence == SEEK_SET) {
    860                 file->pos = off;
     904       
     905        off64_t newoff;
     906        switch (whence) {
     907        case SEEK_SET:
     908                if (off >= 0) {
     909                        file->pos = (aoff64_t) off;
     910                        fibril_mutex_unlock(&file->lock);
     911                        vfs_file_put(file);
     912                        async_answer_1(rid, EOK, off);
     913                        return;
     914                }
     915                break;
     916        case SEEK_CUR:
     917                if ((off >= 0) && (file->pos + off < file->pos)) {
     918                        fibril_mutex_unlock(&file->lock);
     919                        vfs_file_put(file);
     920                        async_answer_0(rid, EOVERFLOW);
     921                        return;
     922                }
     923               
     924                if ((off < 0) && (file->pos < (aoff64_t) -off)) {
     925                        fibril_mutex_unlock(&file->lock);
     926                        vfs_file_put(file);
     927                        async_answer_0(rid, EOVERFLOW);
     928                        return;
     929                }
     930               
     931                file->pos += off;
     932                newoff = (file->pos > OFF64_MAX) ?  OFF64_MAX : file->pos;
     933               
    861934                fibril_mutex_unlock(&file->lock);
    862                 ipc_answer_1(rid, EOK, off);
    863                 return;
    864         }
    865         if (whence == SEEK_CUR) {
    866                 if (file->pos + off < file->pos) {
     935                vfs_file_put(file);
     936                async_answer_2(rid, EOK, LOWER32(newoff),
     937                    UPPER32(newoff));
     938                return;
     939        case SEEK_END:
     940                fibril_rwlock_read_lock(&file->node->contents_rwlock);
     941                aoff64_t size = file->node->size;
     942               
     943                if ((off >= 0) && (size + off < size)) {
     944                        fibril_rwlock_read_unlock(&file->node->contents_rwlock);
    867945                        fibril_mutex_unlock(&file->lock);
    868                         ipc_answer_0(rid, EOVERFLOW);
    869                         return;
    870                 }
    871                 file->pos += off;
    872                 newpos = file->pos;
     946                        vfs_file_put(file);
     947                        async_answer_0(rid, EOVERFLOW);
     948                        return;
     949                }
     950               
     951                if ((off < 0) && (size < (aoff64_t) -off)) {
     952                        fibril_rwlock_read_unlock(&file->node->contents_rwlock);
     953                        fibril_mutex_unlock(&file->lock);
     954                        vfs_file_put(file);
     955                        async_answer_0(rid, EOVERFLOW);
     956                        return;
     957                }
     958               
     959                file->pos = size + off;
     960                newoff = (file->pos > OFF64_MAX) ?  OFF64_MAX : file->pos;
     961               
     962                fibril_rwlock_read_unlock(&file->node->contents_rwlock);
    873963                fibril_mutex_unlock(&file->lock);
    874                 ipc_answer_1(rid, EOK, newpos);
    875                 return;
    876         }
    877         if (whence == SEEK_END) {
    878                 fibril_rwlock_read_lock(&file->node->contents_rwlock);
    879                 size_t size = file->node->size;
    880                 fibril_rwlock_read_unlock(&file->node->contents_rwlock);
    881                 if (size + off < size) {
    882                         fibril_mutex_unlock(&file->lock);
    883                         ipc_answer_0(rid, EOVERFLOW);
    884                         return;
    885                 }
    886                 newpos = size + off;
    887                 fibril_mutex_unlock(&file->lock);
    888                 ipc_answer_1(rid, EOK, newpos);
    889                 return;
    890         }
     964                vfs_file_put(file);
     965                async_answer_2(rid, EOK, LOWER32(newoff), UPPER32(newoff));
     966                return;
     967        }
     968       
    891969        fibril_mutex_unlock(&file->lock);
    892         ipc_answer_0(rid, EINVAL);
    893 }
    894 
    895 int
    896 vfs_truncate_internal(fs_handle_t fs_handle, dev_handle_t dev_handle,
    897     fs_index_t index, size_t size)
    898 {
    899         ipcarg_t rc;
     970        vfs_file_put(file);
     971        async_answer_0(rid, EINVAL);
     972}
     973
     974int vfs_truncate_internal(fs_handle_t fs_handle, devmap_handle_t devmap_handle,
     975    fs_index_t index, aoff64_t size)
     976{
     977        sysarg_t rc;
    900978        int fs_phone;
    901979       
    902980        fs_phone = vfs_grab_phone(fs_handle);
    903         rc = async_req_3_0(fs_phone, VFS_OUT_TRUNCATE, (ipcarg_t)dev_handle,
    904             (ipcarg_t)index, (ipcarg_t)size);
    905         vfs_release_phone(fs_phone);
     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);
    906984        return (int)rc;
    907985}
     
    910988{
    911989        int fd = IPC_GET_ARG1(*request);
    912         size_t size = IPC_GET_ARG2(*request);
     990        aoff64_t size = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(*request),
     991            IPC_GET_ARG3(*request));
    913992        int rc;
    914993
    915994        vfs_file_t *file = vfs_file_get(fd);
    916995        if (!file) {
    917                 ipc_answer_0(rid, ENOENT);
     996                async_answer_0(rid, ENOENT);
    918997                return;
    919998        }
     
    9221001        fibril_rwlock_write_lock(&file->node->contents_rwlock);
    9231002        rc = vfs_truncate_internal(file->node->fs_handle,
    924             file->node->dev_handle, file->node->index, size);
     1003            file->node->devmap_handle, file->node->index, size);
    9251004        if (rc == EOK)
    9261005                file->node->size = size;
     
    9281007
    9291008        fibril_mutex_unlock(&file->lock);
    930         ipc_answer_0(rid, (ipcarg_t)rc);
     1009        vfs_file_put(file);
     1010        async_answer_0(rid, (sysarg_t)rc);
    9311011}
    9321012
     
    9341014{
    9351015        int fd = IPC_GET_ARG1(*request);
    936         size_t size = IPC_GET_ARG2(*request);
    937         ipcarg_t rc;
     1016        sysarg_t rc;
    9381017
    9391018        vfs_file_t *file = vfs_file_get(fd);
    9401019        if (!file) {
    941                 ipc_answer_0(rid, ENOENT);
     1020                async_answer_0(rid, ENOENT);
    9421021                return;
    9431022        }
    9441023
    9451024        ipc_callid_t callid;
    946         if (!ipc_data_read_receive(&callid, NULL)) {
    947                 ipc_answer_0(callid, EINVAL);
    948                 ipc_answer_0(rid, EINVAL);
     1025        if (!async_data_read_receive(&callid, NULL)) {
     1026                vfs_file_put(file);
     1027                async_answer_0(callid, EINVAL);
     1028                async_answer_0(rid, EINVAL);
    9491029                return;
    9501030        }
     
    9551035       
    9561036        aid_t msg;
    957         msg = async_send_3(fs_phone, VFS_OUT_STAT, file->node->dev_handle,
     1037        msg = async_send_3(fs_phone, VFS_OUT_STAT, file->node->devmap_handle,
    9581038            file->node->index, true, NULL);
    959         ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
     1039        async_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
    9601040        async_wait_for(msg, &rc);
    961         vfs_release_phone(fs_phone);
     1041        vfs_release_phone(file->node->fs_handle, fs_phone);
    9621042
    9631043        fibril_mutex_unlock(&file->lock);
    964         ipc_answer_0(rid, rc);
     1044        vfs_file_put(file);
     1045        async_answer_0(rid, rc);
    9651046}
    9661047
    9671048void vfs_stat(ipc_callid_t rid, ipc_call_t *request)
    9681049{
    969         size_t len;
     1050        char *path;
     1051        int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
     1052        if (rc != EOK) {
     1053                async_answer_0(rid, rc);
     1054                return;
     1055        }
     1056       
    9701057        ipc_callid_t callid;
    971 
    972         if (!ipc_data_write_receive(&callid, &len)) {
    973                 ipc_answer_0(callid, EINVAL);
    974                 ipc_answer_0(rid, EINVAL);
    975                 return;
    976         }
    977         char *path = malloc(len + 1);
    978         if (!path) {
    979                 ipc_answer_0(callid, ENOMEM);
    980                 ipc_answer_0(rid, ENOMEM);
    981                 return;
    982         }
    983         int rc;
    984         if ((rc = ipc_data_write_finalize(callid, path, len))) {
    985                 ipc_answer_0(rid, rc);
     1058        if (!async_data_read_receive(&callid, NULL)) {
    9861059                free(path);
    987                 return;
    988         }
    989         path[len] = '\0';
    990 
    991         if (!ipc_data_read_receive(&callid, NULL)) {
    992                 free(path);
    993                 ipc_answer_0(callid, EINVAL);
    994                 ipc_answer_0(rid, EINVAL);
     1060                async_answer_0(callid, EINVAL);
     1061                async_answer_0(rid, EINVAL);
    9951062                return;
    9961063        }
     
    10021069        if (rc != EOK) {
    10031070                fibril_rwlock_read_unlock(&namespace_rwlock);
    1004                 ipc_answer_0(callid, rc);
    1005                 ipc_answer_0(rid, rc);
     1071                async_answer_0(callid, rc);
     1072                async_answer_0(rid, rc);
    10061073                return;
    10071074        }
     
    10091076        if (!node) {
    10101077                fibril_rwlock_read_unlock(&namespace_rwlock);
    1011                 ipc_answer_0(callid, ENOMEM);
    1012                 ipc_answer_0(rid, ENOMEM);
     1078                async_answer_0(callid, ENOMEM);
     1079                async_answer_0(rid, ENOMEM);
    10131080                return;
    10141081        }
     
    10181085        int fs_phone = vfs_grab_phone(node->fs_handle);
    10191086        aid_t msg;
    1020         msg = async_send_3(fs_phone, VFS_OUT_STAT, node->dev_handle,
     1087        msg = async_send_3(fs_phone, VFS_OUT_STAT, node->devmap_handle,
    10211088            node->index, false, NULL);
    1022         ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
    1023        
    1024         ipcarg_t rv;
     1089        async_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
     1090       
     1091        sysarg_t rv;
    10251092        async_wait_for(msg, &rv);
    1026         vfs_release_phone(fs_phone);
    1027 
    1028         ipc_answer_0(rid, rv);
     1093        vfs_release_phone(node->fs_handle, fs_phone);
     1094
     1095        async_answer_0(rid, rv);
    10291096
    10301097        vfs_node_put(node);
     
    10341101{
    10351102        int mode = IPC_GET_ARG1(*request);
    1036 
    1037         size_t len;
    1038         ipc_callid_t callid;
    1039 
    1040         if (!ipc_data_write_receive(&callid, &len)) {
    1041                 ipc_answer_0(callid, EINVAL);
    1042                 ipc_answer_0(rid, EINVAL);
    1043                 return;
    1044         }
    1045         char *path = malloc(len + 1);
    1046         if (!path) {
    1047                 ipc_answer_0(callid, ENOMEM);
    1048                 ipc_answer_0(rid, ENOMEM);
    1049                 return;
    1050         }
    1051         int rc;
    1052         if ((rc = ipc_data_write_finalize(callid, path, len))) {
    1053                 ipc_answer_0(rid, rc);
    1054                 free(path);
    1055                 return;
    1056         }
    1057         path[len] = '\0';
    1058 
     1103       
     1104        char *path;
     1105        int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
     1106        if (rc != EOK) {
     1107                async_answer_0(rid, rc);
     1108                return;
     1109        }
     1110       
    10591111        /* Ignore mode for now. */
    10601112        (void) mode;
     
    10651117        fibril_rwlock_write_unlock(&namespace_rwlock);
    10661118        free(path);
    1067         ipc_answer_0(rid, rc);
     1119        async_answer_0(rid, rc);
    10681120}
    10691121
     
    10711123{
    10721124        int lflag = IPC_GET_ARG1(*request);
    1073 
    1074         size_t len;
    1075         ipc_callid_t callid;
    1076 
    1077         if (!ipc_data_write_receive(&callid, &len)) {
    1078                 ipc_answer_0(callid, EINVAL);
    1079                 ipc_answer_0(rid, EINVAL);
    1080                 return;
    1081         }
    1082         char *path = malloc(len + 1);
    1083         if (!path) {
    1084                 ipc_answer_0(callid, ENOMEM);
    1085                 ipc_answer_0(rid, ENOMEM);
    1086                 return;
    1087         }
    1088         int rc;
    1089         if ((rc = ipc_data_write_finalize(callid, path, len))) {
    1090                 ipc_answer_0(rid, rc);
    1091                 free(path);
    1092                 return;
    1093         }
    1094         path[len] = '\0';
     1125       
     1126        char *path;
     1127        int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
     1128        if (rc != EOK) {
     1129                async_answer_0(rid, rc);
     1130                return;
     1131        }
    10951132       
    10961133        fibril_rwlock_write_lock(&namespace_rwlock);
     
    11011138        if (rc != EOK) {
    11021139                fibril_rwlock_write_unlock(&namespace_rwlock);
    1103                 ipc_answer_0(rid, rc);
     1140                async_answer_0(rid, rc);
    11041141                return;
    11051142        }
     
    11161153        fibril_rwlock_write_unlock(&namespace_rwlock);
    11171154        vfs_node_put(node);
    1118         ipc_answer_0(rid, EOK);
     1155        async_answer_0(rid, EOK);
    11191156}
    11201157
    11211158void vfs_rename(ipc_callid_t rid, ipc_call_t *request)
    11221159{
    1123         size_t olen, nlen;
    1124         ipc_callid_t callid;
    1125         int rc;
    1126 
    11271160        /* Retrieve the old path. */
    1128         if (!ipc_data_write_receive(&callid, &olen)) {
    1129                 ipc_answer_0(callid, EINVAL);
    1130                 ipc_answer_0(rid, EINVAL);
    1131                 return;
    1132         }
    1133         char *old = malloc(olen + 1);
    1134         if (!old) {
    1135                 ipc_answer_0(callid, ENOMEM);
    1136                 ipc_answer_0(rid, ENOMEM);
    1137                 return;
    1138         }
    1139         if ((rc = ipc_data_write_finalize(callid, old, olen))) {
    1140                 ipc_answer_0(rid, rc);
     1161        char *old;
     1162        int rc = async_data_write_accept((void **) &old, true, 0, 0, 0, NULL);
     1163        if (rc != EOK) {
     1164                async_answer_0(rid, rc);
     1165                return;
     1166        }
     1167       
     1168        /* Retrieve the new path. */
     1169        char *new;
     1170        rc = async_data_write_accept((void **) &new, true, 0, 0, 0, NULL);
     1171        if (rc != EOK) {
    11411172                free(old);
    1142                 return;
    1143         }
    1144         old[olen] = '\0';
    1145        
    1146         /* Retrieve the new path. */
    1147         if (!ipc_data_write_receive(&callid, &nlen)) {
    1148                 ipc_answer_0(callid, EINVAL);
    1149                 ipc_answer_0(rid, EINVAL);
    1150                 free(old);
    1151                 return;
    1152         }
    1153         char *new = malloc(nlen + 1);
    1154         if (!new) {
    1155                 ipc_answer_0(callid, ENOMEM);
    1156                 ipc_answer_0(rid, ENOMEM);
    1157                 free(old);
    1158                 return;
    1159         }
    1160         if ((rc = ipc_data_write_finalize(callid, new, nlen))) {
    1161                 ipc_answer_0(rid, rc);
     1173                async_answer_0(rid, rc);
     1174                return;
     1175        }
     1176       
     1177        size_t olen;
     1178        size_t nlen;
     1179        char *oldc = canonify(old, &olen);
     1180        char *newc = canonify(new, &nlen);
     1181       
     1182        if ((!oldc) || (!newc)) {
     1183                async_answer_0(rid, EINVAL);
    11621184                free(old);
    11631185                free(new);
    11641186                return;
    11651187        }
    1166         new[nlen] = '\0';
    1167 
    1168         char *oldc = canonify(old, &olen);
    1169         char *newc = canonify(new, &nlen);
    1170         if (!oldc || !newc) {
    1171                 ipc_answer_0(rid, EINVAL);
    1172                 free(old);
    1173                 free(new);
    1174                 return;
    1175         }
     1188       
    11761189        oldc[olen] = '\0';
    11771190        newc[nlen] = '\0';
     1191       
    11781192        if ((!str_lcmp(newc, oldc, str_length(oldc))) &&
    11791193            ((newc[str_length(oldc)] == '/') ||
     
    11861200                 * - oldc and newc are equal.
    11871201                 */
    1188                 ipc_answer_0(rid, EINVAL);
     1202                async_answer_0(rid, EINVAL);
    11891203                free(old);
    11901204                free(new);
     
    11961210        vfs_lookup_res_t new_par_lr;
    11971211        fibril_rwlock_write_lock(&namespace_rwlock);
     1212       
    11981213        /* Lookup the node belonging to the old file name. */
    11991214        rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL);
    12001215        if (rc != EOK) {
    12011216                fibril_rwlock_write_unlock(&namespace_rwlock);
    1202                 ipc_answer_0(rid, rc);
     1217                async_answer_0(rid, rc);
    12031218                free(old);
    12041219                free(new);
    12051220                return;
    12061221        }
     1222       
    12071223        vfs_node_t *old_node = vfs_node_get(&old_lr);
    12081224        if (!old_node) {
    12091225                fibril_rwlock_write_unlock(&namespace_rwlock);
    1210                 ipc_answer_0(rid, ENOMEM);
     1226                async_answer_0(rid, ENOMEM);
    12111227                free(old);
    12121228                free(new);
    12131229                return;
    12141230        }
     1231       
    12151232        /* Determine the path to the parent of the node with the new name. */
    12161233        char *parentc = str_dup(newc);
    12171234        if (!parentc) {
    12181235                fibril_rwlock_write_unlock(&namespace_rwlock);
    1219                 ipc_answer_0(rid, rc);
     1236                async_answer_0(rid, rc);
    12201237                free(old);
    12211238                free(new);
    12221239                return;
    12231240        }
     1241       
    12241242        char *lastsl = str_rchr(parentc + 1, '/');
    12251243        if (lastsl)
     
    12271245        else
    12281246                parentc[1] = '\0';
     1247       
    12291248        /* Lookup parent of the new file name. */
    12301249        rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL);
     
    12321251        if (rc != EOK) {
    12331252                fibril_rwlock_write_unlock(&namespace_rwlock);
    1234                 ipc_answer_0(rid, rc);
     1253                async_answer_0(rid, rc);
    12351254                free(old);
    12361255                free(new);
    12371256                return;
    12381257        }
     1258       
    12391259        /* Check whether linking to the same file system instance. */
    12401260        if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) ||
    1241             (old_node->dev_handle != new_par_lr.triplet.dev_handle)) {
     1261            (old_node->devmap_handle != new_par_lr.triplet.devmap_handle)) {
    12421262                fibril_rwlock_write_unlock(&namespace_rwlock);
    1243                 ipc_answer_0(rid, EXDEV);       /* different file systems */
     1263                async_answer_0(rid, EXDEV);     /* different file systems */
    12441264                free(old);
    12451265                free(new);
    12461266                return;
    12471267        }
     1268       
    12481269        /* Destroy the old link for the new name. */
    12491270        vfs_node_t *new_node = NULL;
    12501271        rc = vfs_lookup_internal(newc, L_UNLINK, &new_lr, NULL);
     1272       
    12511273        switch (rc) {
    12521274        case ENOENT:
     
    12571279                if (!new_node) {
    12581280                        fibril_rwlock_write_unlock(&namespace_rwlock);
    1259                         ipc_answer_0(rid, ENOMEM);
     1281                        async_answer_0(rid, ENOMEM);
    12601282                        free(old);
    12611283                        free(new);
     
    12681290        default:
    12691291                fibril_rwlock_write_unlock(&namespace_rwlock);
    1270                 ipc_answer_0(rid, ENOTEMPTY);
     1292                async_answer_0(rid, ENOTEMPTY);
    12711293                free(old);
    12721294                free(new);
    12731295                return;
    12741296        }
     1297       
    12751298        /* Create the new link for the new name. */
    12761299        rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index);
     
    12791302                if (new_node)
    12801303                        vfs_node_put(new_node);
    1281                 ipc_answer_0(rid, rc);
     1304                async_answer_0(rid, rc);
    12821305                free(old);
    12831306                free(new);
    12841307                return;
    12851308        }
     1309       
    12861310        fibril_mutex_lock(&nodes_mutex);
    12871311        old_node->lnkcnt++;
    12881312        fibril_mutex_unlock(&nodes_mutex);
     1313       
    12891314        /* Destroy the link for the old name. */
    12901315        rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL);
     
    12941319                if (new_node)
    12951320                        vfs_node_put(new_node);
    1296                 ipc_answer_0(rid, rc);
     1321                async_answer_0(rid, rc);
    12971322                free(old);
    12981323                free(new);
    12991324                return;
    13001325        }
     1326       
    13011327        fibril_mutex_lock(&nodes_mutex);
    13021328        old_node->lnkcnt--;
     
    13041330        fibril_rwlock_write_unlock(&namespace_rwlock);
    13051331        vfs_node_put(old_node);
     1332       
    13061333        if (new_node)
    13071334                vfs_node_put(new_node);
     1335       
    13081336        free(old);
    13091337        free(new);
    1310         ipc_answer_0(rid, EOK);
     1338        async_answer_0(rid, EOK);
     1339}
     1340
     1341void vfs_dup(ipc_callid_t rid, ipc_call_t *request)
     1342{
     1343        int oldfd = IPC_GET_ARG1(*request);
     1344        int newfd = IPC_GET_ARG2(*request);
     1345       
     1346        /* If the file descriptors are the same, do nothing. */
     1347        if (oldfd == newfd) {
     1348                async_answer_1(rid, EOK, newfd);
     1349                return;
     1350        }
     1351       
     1352        /* Lookup the file structure corresponding to oldfd. */
     1353        vfs_file_t *oldfile = vfs_file_get(oldfd);
     1354        if (!oldfile) {
     1355                async_answer_0(rid, EBADF);
     1356                return;
     1357        }
     1358       
     1359        /*
     1360         * Lock the open file structure so that no other thread can manipulate
     1361         * the same open file at a time.
     1362         */
     1363        fibril_mutex_lock(&oldfile->lock);
     1364       
     1365        /* Lookup an open file structure possibly corresponding to newfd. */
     1366        vfs_file_t *newfile = vfs_file_get(newfd);
     1367        if (newfile) {
     1368                /* Close the originally opened file. */
     1369                int ret = vfs_close_internal(newfile);
     1370                if (ret != EOK) {
     1371                        fibril_mutex_unlock(&oldfile->lock);
     1372                        vfs_file_put(oldfile);
     1373                        vfs_file_put(newfile);
     1374                        async_answer_0(rid, ret);
     1375                        return;
     1376                }
     1377               
     1378                ret = vfs_fd_free(newfd);
     1379                if (ret != EOK) {
     1380                        fibril_mutex_unlock(&oldfile->lock);
     1381                        vfs_file_put(oldfile);
     1382                        vfs_file_put(newfile);
     1383                        async_answer_0(rid, ret);
     1384                        return;
     1385                }
     1386                vfs_file_put(newfile);
     1387        }
     1388       
     1389        /* Assign the old file to newfd. */
     1390        int ret = vfs_fd_assign(oldfile, newfd);
     1391        fibril_mutex_unlock(&oldfile->lock);
     1392        vfs_file_put(oldfile);
     1393       
     1394        if (ret != EOK)
     1395                async_answer_0(rid, ret);
     1396        else
     1397                async_answer_1(rid, EOK, newfd);
    13111398}
    13121399
Note: See TracChangeset for help on using the changeset viewer.