Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/tmpfs/tmpfs_ops.c

    r1313ee9 red903174  
    2929/** @addtogroup fs
    3030 * @{
    31  */ 
     31 */
    3232
    3333/**
     
    4040#include "../../vfs/vfs.h"
    4141#include <ipc/ipc.h>
     42#include <macros.h>
     43#include <limits.h>
    4244#include <async.h>
    4345#include <errno.h>
     
    9395}
    9496
    95 static size_t tmpfs_size_get(fs_node_t *fn)
     97static aoff64_t tmpfs_size_get(fs_node_t *fn)
    9698{
    9799        return TMPFS_NODE(fn)->size;
     
    147149hash_table_t nodes;
    148150
    149 #define NODES_KEY_INDEX 0
    150 #define NODES_KEY_DEV   1
     151#define NODES_KEY_DEV   0       
     152#define NODES_KEY_INDEX 1
    151153
    152154/* Implementation of hash table interface for the nodes hash table. */
     
    160162        tmpfs_node_t *nodep = hash_table_get_instance(item, tmpfs_node_t,
    161163            nh_link);
    162         return (nodep->index == key[NODES_KEY_INDEX] &&
    163             nodep->dev_handle == key[NODES_KEY_DEV]);
     164       
     165        switch (keys) {
     166        case 1:
     167                return (nodep->dev_handle == key[NODES_KEY_DEV]);
     168        case 2:
     169                return ((nodep->dev_handle == key[NODES_KEY_DEV]) &&
     170                    (nodep->index == key[NODES_KEY_INDEX]));
     171        default:
     172                assert((keys == 1) || (keys == 2));
     173        }
     174
     175        return 0;
    164176}
    165177
    166178static void nodes_remove_callback(link_t *item)
    167179{
     180        tmpfs_node_t *nodep = hash_table_get_instance(item, tmpfs_node_t,
     181            nh_link);
     182
     183        while (!list_empty(&nodep->cs_head)) {
     184                tmpfs_dentry_t *dentryp = list_get_instance(nodep->cs_head.next,
     185                    tmpfs_dentry_t, link);
     186
     187                assert(nodep->type == TMPFS_DIRECTORY);
     188                list_remove(&dentryp->link);
     189                free(dentryp);
     190        }
     191
     192        if (nodep->data) {
     193                assert(nodep->type == TMPFS_FILE);
     194                free(nodep->data);
     195        }
     196        free(nodep->bp);
     197        free(nodep);
    168198}
    169199
     
    215245}
    216246
     247static void tmpfs_instance_done(dev_handle_t dev_handle)
     248{
     249        unsigned long key[] = {
     250                [NODES_KEY_DEV] = dev_handle
     251        };
     252        /*
     253         * Here we are making use of one special feature of our hash table
     254         * implementation, which allows to remove more items based on a partial
     255         * key match. In the following, we are going to remove all nodes
     256         * matching our device handle. The nodes_remove_callback() function will
     257         * take care of resource deallocation.
     258         */
     259        hash_table_remove(&nodes, key, 1);
     260}
     261
    217262int tmpfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
    218263{
     
    237282{
    238283        unsigned long key[] = {
    239                 [NODES_KEY_INDEX] = index,
    240                 [NODES_KEY_DEV] = dev_handle
     284                [NODES_KEY_DEV] = dev_handle,
     285                [NODES_KEY_INDEX] = index
    241286        };
    242287        link_t *lnk = hash_table_find(&nodes, key);
     
    296341        /* Insert the new node into the nodes hash table. */
    297342        unsigned long key[] = {
    298                 [NODES_KEY_INDEX] = nodep->index,
    299                 [NODES_KEY_DEV] = nodep->dev_handle
     343                [NODES_KEY_DEV] = nodep->dev_handle,
     344                [NODES_KEY_INDEX] = nodep->index
    300345        };
    301346        hash_table_insert(&nodes, key, &nodep->nh_link);
     
    312357
    313358        unsigned long key[] = {
    314                 [NODES_KEY_INDEX] = nodep->index,
    315                 [NODES_KEY_DEV] = nodep->dev_handle
     359                [NODES_KEY_DEV] = nodep->dev_handle,
     360                [NODES_KEY_INDEX] = nodep->index
    316361        };
    317362        hash_table_remove(&nodes, key, 2);
    318363
    319         if (nodep->type == TMPFS_FILE)
    320                 free(nodep->data);
    321         free(nodep->bp);
    322         free(nodep);
     364        /*
     365         * The nodes_remove_callback() function takes care of the actual
     366         * resource deallocation.
     367         */
    323368        return EOK;
    324369}
     
    398443{
    399444        dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
     445        fs_node_t *rootfn;
    400446        int rc;
    401 
    402         /* accept the mount options */
    403         ipc_callid_t callid;
    404         size_t size;
    405         if (!async_data_write_receive(&callid, &size)) {
    406                 ipc_answer_0(callid, EINVAL);
    407                 ipc_answer_0(rid, EINVAL);
    408                 return;
    409         }
    410         char *opts = malloc(size + 1);
    411         if (!opts) {
    412                 ipc_answer_0(callid, ENOMEM);
    413                 ipc_answer_0(rid, ENOMEM);
    414                 return;
    415         }
    416         ipcarg_t retval = async_data_write_finalize(callid, opts, size);
    417         if (retval != EOK) {
    418                 ipc_answer_0(rid, retval);
     447       
     448        /* Accept the mount options. */
     449        char *opts;
     450        rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
     451        if (rc != EOK) {
     452                ipc_answer_0(rid, rc);
     453                return;
     454        }
     455
     456        /* Check if this device is not already mounted. */
     457        rc = tmpfs_root_get(&rootfn, dev_handle);
     458        if ((rc == EOK) && (rootfn)) {
     459                (void) tmpfs_node_put(rootfn);
    419460                free(opts);
    420                 return;
    421         }
    422         opts[size] = '\0';
     461                ipc_answer_0(rid, EEXIST);
     462                return;
     463        }
    423464
    424465        /* Initialize TMPFS instance. */
    425466        if (!tmpfs_instance_init(dev_handle)) {
     467                free(opts);
    426468                ipc_answer_0(rid, ENOMEM);
    427469                return;
    428470        }
    429471
    430         fs_node_t *rootfn;
    431472        rc = tmpfs_root_get(&rootfn, dev_handle);
    432473        assert(rc == EOK);
     
    442483                    rootp->lnkcnt);
    443484        }
     485        free(opts);
    444486}
    445487
     
    449491}
    450492
     493void tmpfs_unmounted(ipc_callid_t rid, ipc_call_t *request)
     494{
     495        dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
     496
     497        tmpfs_instance_done(dev_handle);
     498        ipc_answer_0(rid, EOK);
     499}
     500
     501void tmpfs_unmount(ipc_callid_t rid, ipc_call_t *request)
     502{
     503        libfs_unmount(&tmpfs_libfs_ops, rid, request);
     504}
     505
    451506void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request)
    452507{
     
    456511void tmpfs_read(ipc_callid_t rid, ipc_call_t *request)
    457512{
    458         dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
    459         fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    460         off_t pos = (off_t)IPC_GET_ARG3(*request);
    461 
     513        dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
     514        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     515        aoff64_t pos =
     516            (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
     517       
    462518        /*
    463519         * Lookup the respective TMPFS node.
     
    465521        link_t *hlp;
    466522        unsigned long key[] = {
    467                 [NODES_KEY_INDEX] = index,
    468523                [NODES_KEY_DEV] = dev_handle,
     524                [NODES_KEY_INDEX] = index
    469525        };
    470526        hlp = hash_table_find(&nodes, key);
     
    475531        tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
    476532            nh_link);
    477 
     533       
    478534        /*
    479535         * Receive the read request.
     
    482538        size_t size;
    483539        if (!async_data_read_receive(&callid, &size)) {
    484                 ipc_answer_0(callid, EINVAL);   
     540                ipc_answer_0(callid, EINVAL);
    485541                ipc_answer_0(rid, EINVAL);
    486542                return;
     
    489545        size_t bytes;
    490546        if (nodep->type == TMPFS_FILE) {
    491                 bytes = max(0, min(nodep->size - pos, size));
     547                bytes = min(nodep->size - pos, size);
    492548                (void) async_data_read_finalize(callid, nodep->data + pos,
    493549                    bytes);
     
    495551                tmpfs_dentry_t *dentryp;
    496552                link_t *lnk;
    497                 int i;
     553                aoff64_t i;
    498554               
    499555                assert(nodep->type == TMPFS_DIRECTORY);
     
    505561                 */
    506562                for (i = 0, lnk = nodep->cs_head.next;
    507                     i < pos && lnk != &nodep->cs_head;
     563                    (i < pos) && (lnk != &nodep->cs_head);
    508564                    i++, lnk = lnk->next)
    509565                        ;
     
    530586void tmpfs_write(ipc_callid_t rid, ipc_call_t *request)
    531587{
    532         dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
    533         fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    534         off_t pos = (off_t)IPC_GET_ARG3(*request);
    535 
     588        dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
     589        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     590        aoff64_t pos =
     591            (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
     592       
    536593        /*
    537594         * Lookup the respective TMPFS node.
     
    539596        link_t *hlp;
    540597        unsigned long key[] = {
    541                 [NODES_KEY_INDEX] = index,
    542                 [NODES_KEY_DEV] = dev_handle
     598                [NODES_KEY_DEV] = dev_handle,
     599                [NODES_KEY_INDEX] = index
    543600        };
    544601        hlp = hash_table_find(&nodes, key);
     
    594651void tmpfs_truncate(ipc_callid_t rid, ipc_call_t *request)
    595652{
     653        dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
     654        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     655        aoff64_t size =
     656            (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
     657       
     658        /*
     659         * Lookup the respective TMPFS node.
     660         */
     661        unsigned long key[] = {
     662                [NODES_KEY_DEV] = dev_handle,
     663                [NODES_KEY_INDEX] = index
     664        };
     665        link_t *hlp = hash_table_find(&nodes, key);
     666        if (!hlp) {
     667                ipc_answer_0(rid, ENOENT);
     668                return;
     669        }
     670        tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
     671            nh_link);
     672       
     673        if (size == nodep->size) {
     674                ipc_answer_0(rid, EOK);
     675                return;
     676        }
     677       
     678        if (size > SIZE_MAX) {
     679                ipc_answer_0(rid, ENOMEM);
     680                return;
     681        }
     682       
     683        void *newdata = realloc(nodep->data, size);
     684        if (!newdata) {
     685                ipc_answer_0(rid, ENOMEM);
     686                return;
     687        }
     688       
     689        if (size > nodep->size) {
     690                size_t delta = size - nodep->size;
     691                memset(newdata + nodep->size, 0, delta);
     692        }
     693       
     694        nodep->size = size;
     695        nodep->data = newdata;
     696        ipc_answer_0(rid, EOK);
     697}
     698
     699void tmpfs_close(ipc_callid_t rid, ipc_call_t *request)
     700{
     701        ipc_answer_0(rid, EOK);
     702}
     703
     704void tmpfs_destroy(ipc_callid_t rid, ipc_call_t *request)
     705{
    596706        dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
    597707        fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    598         size_t size = (off_t)IPC_GET_ARG3(*request);
    599 
    600         /*
    601          * Lookup the respective TMPFS node.
    602          */
     708        int rc;
     709
    603710        link_t *hlp;
    604711        unsigned long key[] = {
    605                 [NODES_KEY_INDEX] = index,
    606                 [NODES_KEY_DEV] = dev_handle
     712                [NODES_KEY_DEV] = dev_handle,
     713                [NODES_KEY_INDEX] = index
    607714        };
    608715        hlp = hash_table_find(&nodes, key);
     
    613720        tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
    614721            nh_link);
    615 
    616         if (size == nodep->size) {
    617                 ipc_answer_0(rid, EOK);
    618                 return;
    619         }
    620 
    621         void *newdata = realloc(nodep->data, size);
    622         if (!newdata) {
    623                 ipc_answer_0(rid, ENOMEM);
    624                 return;
    625         }
    626         if (size > nodep->size) {
    627                 size_t delta = size - nodep->size;
    628                 memset(newdata + nodep->size, 0, delta);
    629         }
    630         nodep->size = size;
    631         nodep->data = newdata;
    632         ipc_answer_0(rid, EOK);
    633 }
    634 
    635 void tmpfs_close(ipc_callid_t rid, ipc_call_t *request)
    636 {
    637         ipc_answer_0(rid, EOK);
    638 }
    639 
    640 void tmpfs_destroy(ipc_callid_t rid, ipc_call_t *request)
    641 {
    642         dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
    643         fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    644         int rc;
    645 
    646         link_t *hlp;
    647         unsigned long key[] = {
    648                 [NODES_KEY_INDEX] = index,
    649                 [NODES_KEY_DEV] = dev_handle
    650         };
    651         hlp = hash_table_find(&nodes, key);
    652         if (!hlp) {
    653                 ipc_answer_0(rid, ENOENT);
    654                 return;
    655         }
    656         tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
    657             nh_link);
    658722        rc = tmpfs_destroy_node(FS_NODE(nodep));
    659723        ipc_answer_0(rid, rc);
Note: See TracChangeset for help on using the changeset viewer.