Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 8d1aab7 in mainline


Ignore:
Timestamp:
2010-11-24T18:59:47Z (11 years ago)
Author:
Martin Sucha <sucha14@…>
Branches:
lfn, master
Children:
f5648d8
Parents:
5bd4f2c
Message:

Changes for simple pipefs behaviour. Currently it does not support waiting for data.

Location:
uspace/srv/fs/pipefs
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/pipefs/pipefs.h

    r5bd4f2c r8d1aab7  
    6666        pipefs_dentry_type_t type;
    6767        unsigned lnkcnt;        /**< Link count. */
     68        /* Following is for nodes of type PIPEFS_FILE */
     69        aoff64_t start;         /**< File offset where first data block resides */
    6870        size_t size;            /**< File size if type is PIPEFS_FILE. */
    69         void *data;             /**< File content's if type is PIPEFS_FILE. */
    70         link_t cs_head;         /**< Head of child's siblings list. */
     71        link_t data_head;       /**< Head of data blocks list for PIPEFS_FILE. */
     72        /* This is for directory */
     73        link_t cs_head;         /**< Head of child's siblings list. */ 
    7174} pipefs_node_t;
     75
     76typedef struct pipefs_data_block {
     77        link_t link;            /**< Linkage for the list of data blocks */
     78        size_t size;            /**< Size of this block */
     79        void *data;                     /**< Data for this block */
     80} pipefs_data_block_t;
    7281
    7382extern fs_reg_t pipefs_reg;
  • uspace/srv/fs/pipefs/pipefs_ops.c

    r5bd4f2c r8d1aab7  
    190190        }
    191191
    192         if (nodep->data) {
     192        while (!list_empty(&nodep->data_head)) {
    193193                assert(nodep->type == PIPEFS_FILE);
    194                 free(nodep->data);
     194               
     195                pipefs_data_block_t *data_block = list_get_instance(nodep->data_head.next,
     196                    pipefs_data_block_t, link);
     197               
     198                list_remove(&data_block->link);
     199                free(data_block->data);
     200                free(data_block);
    195201        }
    196202        free(nodep->bp);
     
    212218        nodep->type = PIPEFS_NONE;
    213219        nodep->lnkcnt = 0;
     220        nodep->start = 0;
    214221        nodep->size = 0;
    215         nodep->data = NULL;
     222        list_initialize(&nodep->data_head);
    216223        link_initialize(&nodep->nh_link);
    217224        list_initialize(&nodep->cs_head);
     
    536543        size_t bytes;
    537544        if (nodep->type == PIPEFS_FILE) {
    538                 bytes = min(nodep->size - pos, size);
    539                 (void) async_data_read_finalize(callid, nodep->data + pos,
    540                     bytes);
     545                /*
     546                 * Check if we still have the requested data.
     547                 * This may happen if the client seeked backwards
     548                 */
     549                if (pos < nodep->start) {
     550                        ipc_answer_0(callid, ENOTSUP);
     551                        ipc_answer_0(rid, ENOTSUP);
     552                        return;
     553                }
     554               
     555                /*
     556                 * Free all data blocks that end before pos.
     557                 * This is in case the client seeked forward
     558                 */
     559                while (!list_empty(&nodep->data_head)) {
     560                        pipefs_data_block_t *data_block =
     561                            list_get_instance(nodep->data_head.next,
     562                                pipefs_data_block_t, link);
     563               
     564                        aoff64_t block_end = nodep->start + data_block->size;
     565                       
     566                        if (block_end > pos) {
     567                                break;
     568                        }
     569                       
     570                        list_remove(&data_block->link);
     571                        free(data_block->data);
     572                        free(data_block);
     573                        nodep->start = block_end;
     574                }
     575               
     576                if (!list_empty(&nodep->data_head)) {
     577                        /* We have data block, so let's return its portion after pos */
     578                        pipefs_data_block_t *data_block =
     579                            list_get_instance(nodep->data_head.next,
     580                                pipefs_data_block_t, link);
     581                       
     582                        assert(nodep->start <= pos);
     583                       
     584                        aoff64_t block_end = nodep->start + data_block->size;
     585                        size_t block_offset = pos - nodep->start;
     586                       
     587                        assert(block_end > pos);
     588                       
     589                        bytes = min(block_end - pos, size);
     590                        (void) async_data_read_finalize(callid,
     591                            data_block->data + block_offset,
     592                            bytes);
     593                       
     594                        if (nodep->start + block_offset + bytes == block_end) {
     595                                /* Free the data block - it was fully read */
     596                                list_remove(&data_block->link);
     597                                free(data_block->data);
     598                                free(data_block);
     599                                nodep->start = block_end;
     600                        }
     601                }
     602                else {
     603                        /*
     604                         * there is no data
     605                         * TODO implement waiting for the data
     606                         * and remove this else clause
     607                         */
     608                        ipc_answer_0(callid, ENOTSUP);
     609                        ipc_answer_1(rid, ENOTSUP, 0);
     610                        return;
     611                }
    541612        } else {
    542613                pipefs_dentry_t *dentryp;
     
    610681
    611682        /*
    612          * Check whether the file needs to grow.
    613          */
    614         if (pos + size <= nodep->size) {
    615                 /* The file size is not changing. */
    616                 (void) async_data_write_finalize(callid, nodep->data + pos, size);
    617                 ipc_answer_2(rid, EOK, size, nodep->size);
    618                 return;
    619         }
    620         size_t delta = (pos + size) - nodep->size;
    621         /*
    622          * At this point, we are deliberately extremely straightforward and
    623          * simply realloc the contents of the file on every write that grows the
    624          * file. In the end, the situation might not be as bad as it may look:
    625          * our heap allocator can save us and just grow the block whenever
    626          * possible.
    627          */
    628         void *newdata = realloc(nodep->data, nodep->size + delta);
     683         * Check whether we are writing to the end
     684         */
     685        if (pos != nodep->size) {
     686                ipc_answer_0(callid, ENOTSUP);
     687                ipc_answer_2(rid, EOK, 0, nodep->size);
     688                return;
     689        }
     690       
     691        /*
     692         * Allocate a buffer for the new data.
     693         * Currently we accept any size, create a data block from this
     694         * and append it to the end of a file
     695         */
     696        void *newdata = malloc(size);
    629697        if (!newdata) {
    630698                ipc_answer_0(callid, ENOMEM);
     
    632700                return;
    633701        }
    634         /* Clear any newly allocated memory in order to emulate gaps. */
    635         memset(newdata + nodep->size, 0, delta);
    636         nodep->size += delta;
    637         nodep->data = newdata;
    638         (void) async_data_write_finalize(callid, nodep->data + pos, size);
     702       
     703        pipefs_data_block_t *newblock = malloc(sizeof(pipefs_data_block_t));
     704       
     705        if (!newblock) {
     706                free(newdata);
     707                ipc_answer_0(callid, ENOMEM);
     708                ipc_answer_2(rid, EOK, 0, nodep->size);
     709                return;
     710        }
     711       
     712        int rc = async_data_write_finalize(callid, newdata, size);
     713       
     714        if (rc != EOK) {
     715                free(newblock);
     716                free(newdata);
     717                ipc_answer_0(callid, rc);
     718                ipc_answer_2(rid, EOK, 0, nodep->size);
     719                return;
     720        }
     721       
     722        link_initialize(&newblock->link);
     723        newblock->size = size;
     724        newblock->data = newdata;
     725        list_append(&newblock->link, &nodep->data_head);
     726       
     727        nodep->size += size;
     728       
    639729        ipc_answer_2(rid, EOK, size, nodep->size);
    640730}
     
    642732void pipefs_truncate(ipc_callid_t rid, ipc_call_t *request)
    643733{
    644         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    645         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    646         aoff64_t size =
    647             (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
    648        
    649         /*
    650          * Lookup the respective PIPEFS node.
    651          */
    652         unsigned long key[] = {
    653                 [NODES_KEY_DEV] = devmap_handle,
    654                 [NODES_KEY_INDEX] = index
    655         };
    656         link_t *hlp = hash_table_find(&nodes, key);
    657         if (!hlp) {
    658                 ipc_answer_0(rid, ENOENT);
    659                 return;
    660         }
    661         pipefs_node_t *nodep = hash_table_get_instance(hlp, pipefs_node_t,
    662             nh_link);
    663        
    664         if (size == nodep->size) {
    665                 ipc_answer_0(rid, EOK);
    666                 return;
    667         }
    668        
    669         if (size > SIZE_MAX) {
    670                 ipc_answer_0(rid, ENOMEM);
    671                 return;
    672         }
    673        
    674         void *newdata = realloc(nodep->data, size);
    675         if (!newdata) {
    676                 ipc_answer_0(rid, ENOMEM);
    677                 return;
    678         }
    679        
    680         if (size > nodep->size) {
    681                 size_t delta = size - nodep->size;
    682                 memset(newdata + nodep->size, 0, delta);
    683         }
    684        
    685         nodep->size = size;
    686         nodep->data = newdata;
    687         ipc_answer_0(rid, EOK);
     734        /*
     735         * PIPEFS does not support resizing of files
     736         */
     737        ipc_answer_0(rid, ENOTSUP);
    688738}
    689739
Note: See TracChangeset for help on using the changeset viewer.