Subversion Repositories HelenOS

Rev

Rev 3497 | Rev 3500 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3497 Rev 3499
Line 48... Line 48...
48
#include <libadt/hash_table.h>
48
#include <libadt/hash_table.h>
49
#include <libadt/list.h>
49
#include <libadt/list.h>
50
#include <assert.h>
50
#include <assert.h>
51
#include <futex.h>
51
#include <futex.h>
52
#include <sys/mman.h>
52
#include <sys/mman.h>
-
 
53
#include <align.h>
53
 
54
 
54
#define BS_BLOCK        0
55
#define BS_BLOCK        0
55
#define BS_SIZE         512
56
#define BS_SIZE         512
56
 
57
 
57
/** Futex protecting the list of cached free FAT nodes. */
58
/** Futex protecting the list of cached free FAT nodes. */
Line 104... Line 105...
104
 
105
 
105
/* TODO move somewhere else */
106
/* TODO move somewhere else */
106
typedef struct {
107
typedef struct {
107
    void *data;
108
    void *data;
108
    size_t size;
109
    size_t size;
-
 
110
    bool dirty;
109
} block_t;
111
} block_t;
110
 
112
 
111
static block_t *block_get(dev_handle_t dev_handle, off_t offset, size_t bs)
113
static block_t *block_get(dev_handle_t dev_handle, off_t offset, size_t bs)
112
{
114
{
113
    /* FIXME */
115
    /* FIXME */
Line 845... Line 847...
845
 
847
 
846
    fat_node_put(nodep);
848
    fat_node_put(nodep);
847
    ipc_answer_1(rid, EOK, (ipcarg_t)bytes);
849
    ipc_answer_1(rid, EOK, (ipcarg_t)bytes);
848
}
850
}
849
 
851
 
-
 
852
static void fat_fill_gap(fat_node_t *nodep, off_t start, off_t stop)
-
 
853
{
-
 
854
    /* TODO */
-
 
855
}
-
 
856
 
850
void fat_write(ipc_callid_t rid, ipc_call_t *request)
857
void fat_write(ipc_callid_t rid, ipc_call_t *request)
851
{
858
{
-
 
859
    dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
-
 
860
    fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
-
 
861
    off_t pos = (off_t)IPC_GET_ARG3(*request);
-
 
862
    fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index);
-
 
863
    size_t bytes;
-
 
864
    block_t *b, *bb;
-
 
865
    uint16_t bps;
-
 
866
    unsigned spc;
-
 
867
    off_t clst_boundary;
-
 
868
   
-
 
869
    if (!nodep) {
-
 
870
        ipc_answer_0(rid, ENOENT);
-
 
871
        return;
-
 
872
    }
-
 
873
   
-
 
874
    /* XXX remove me when you are ready */
-
 
875
    {
852
    ipc_answer_0(rid, ENOTSUP);
876
        ipc_answer_0(rid, ENOTSUP);
-
 
877
        fat_node_put(nodep);
-
 
878
        return;
-
 
879
    }
-
 
880
 
-
 
881
    ipc_callid_t callid;
-
 
882
    size_t len;
-
 
883
    if (!ipc_data_write_receive(&callid, &len)) {
-
 
884
        fat_node_put(nodep);
-
 
885
        ipc_answer_0(callid, EINVAL);
-
 
886
        ipc_answer_0(rid, EINVAL);
-
 
887
        return;
-
 
888
    }
-
 
889
 
-
 
890
    /*
-
 
891
     * In all scenarios, we will attempt to write out only one block worth
-
 
892
     * of data at maximum. There might be some more efficient approaches,
-
 
893
     * but this one greatly simplifies fat_write(). Note that we can afford
-
 
894
     * to do this because the client must be ready to handle the return
-
 
895
     * value signalizing a smaller number of bytes written.
-
 
896
     */
-
 
897
    bytes = min(len, bps - pos % bps);
-
 
898
 
-
 
899
    bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
-
 
900
    bps = uint16_t_le2host(FAT_BS(bb)->bps);
-
 
901
    spc = FAT_BS(bb)->spc;
-
 
902
    block_put(bb);
-
 
903
   
-
 
904
    clst_boundary = ROUND_UP(nodep->size, bps * spc);
-
 
905
    if (pos < clst_boundary) {
-
 
906
        /*
-
 
907
         * This is the easier case - we are either overwriting already
-
 
908
         * existing contents or writing behind the EOF, but still within
-
 
909
         * the limits of the last cluster. The node size may grow to the
-
 
910
         * next block size boundary.
-
 
911
         */
-
 
912
        if (pos > nodep->size)
-
 
913
            fat_fill_gap(nodep, nodep->size, pos);
-
 
914
        b = fat_block_get(nodep, pos / bps);
-
 
915
        (void) ipc_data_write_finalize(callid, b->data + pos % bps,
-
 
916
            bytes);
-
 
917
        b->dirty = true;        /* need to sync block */
-
 
918
        if (pos + bytes > nodep->size) {
-
 
919
            nodep->size = pos + bytes;
-
 
920
            nodep->dirty = true;    /* need to sync node */
-
 
921
        }
-
 
922
        block_put(b);
-
 
923
        fat_node_put(nodep);
-
 
924
        ipc_answer_1(rid, EOK, bytes); 
-
 
925
        return;
-
 
926
    } else {
-
 
927
        /*
-
 
928
         * This is the more difficult case. We must allocate new
-
 
929
         * clusters for the node and zero them out.
-
 
930
         */
-
 
931
        unsigned nclsts;
-
 
932
       
-
 
933
        nclsts = (ROUND_UP(pos + bytes, bps * spc) - clst_boundary) /
-
 
934
            bps * spc;
-
 
935
 
-
 
936
    }
-
 
937
   
853
}
938
}
854
 
939
 
855
/**
940
/**
856
 * @}
941
 * @}
857
 */
942
 */