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 | */ |