Changeset 0f57d0e in mainline
- Timestamp:
- 2008-10-26T14:10:53Z (16 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- b1178d0
- Parents:
- 033ef7d3
- Location:
- uspace/srv/fs/fat
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat.h
r033ef7d3 r0f57d0e 34 34 #define FAT_FAT_H_ 35 35 36 #include "fat_fat.h" 36 37 #include <ipc/ipc.h> 37 38 #include <libfs.h> … … 44 45 #define dprintf(...) printf(__VA_ARGS__) 45 46 #endif 47 48 #define min(a, b) ((a) < (b) ? (a) : (b)) 49 50 #define BS_BLOCK 0 51 #define BS_SIZE 512 46 52 47 53 typedef struct { … … 116 122 } __attribute__ ((packed)) fat_bs_t; 117 123 118 typedef uint16_t fat_cluster_t; 124 #define FAT_BS(b) ((fat_bs_t *)((b)->data)) 119 125 120 126 typedef enum { … … 192 198 } fat_node_t; 193 199 200 /* TODO move somewhere else */ 201 typedef struct block { 202 void *data; 203 size_t size; 204 bool dirty; 205 } block_t; 206 207 extern block_t *block_get(dev_handle_t, off_t, size_t); 208 extern void block_put(block_t *); 209 194 210 extern fs_reg_t fat_reg; 195 211 -
uspace/srv/fs/fat/fat_fat.c
r033ef7d3 r0f57d0e 36 36 */ 37 37 38 #include "fat_fat.h" 39 #include "fat_dentry.h" 40 #include "fat.h" 41 #include "../../vfs/vfs.h" 42 #include <libfs.h> 43 #include <errno.h> 44 #include <byteorder.h> 45 #include <align.h> 46 #include <assert.h> 47 48 block_t * 49 _fat_block_get(dev_handle_t dev_handle, fat_cluster_t firstc, off_t offset) 50 { 51 block_t *bb; 52 block_t *b; 53 unsigned bps; 54 unsigned spc; 55 unsigned rscnt; /* block address of the first FAT */ 56 unsigned fatcnt; 57 unsigned rde; 58 unsigned rds; /* root directory size */ 59 unsigned sf; 60 unsigned ssa; /* size of the system area */ 61 unsigned clusters; 62 fat_cluster_t clst = firstc; 63 unsigned i; 64 65 bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); 66 bps = uint16_t_le2host(FAT_BS(bb)->bps); 67 spc = FAT_BS(bb)->spc; 68 rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt); 69 fatcnt = FAT_BS(bb)->fatcnt; 70 rde = uint16_t_le2host(FAT_BS(bb)->root_ent_max); 71 sf = uint16_t_le2host(FAT_BS(bb)->sec_per_fat); 72 block_put(bb); 73 74 rds = (sizeof(fat_dentry_t) * rde) / bps; 75 rds += ((sizeof(fat_dentry_t) * rde) % bps != 0); 76 ssa = rscnt + fatcnt * sf + rds; 77 78 if (firstc == FAT_CLST_ROOT) { 79 /* root directory special case */ 80 assert(offset < rds); 81 b = block_get(dev_handle, rscnt + fatcnt * sf + offset, bps); 82 return b; 83 } 84 85 clusters = offset / spc; 86 for (i = 0; i < clusters; i++) { 87 unsigned fsec; /* sector offset relative to FAT1 */ 88 unsigned fidx; /* FAT1 entry index */ 89 90 assert(clst >= FAT_CLST_FIRST && clst < FAT_CLST_BAD); 91 fsec = (clst * sizeof(fat_cluster_t)) / bps; 92 fidx = clst % (bps / sizeof(fat_cluster_t)); 93 /* read FAT1 */ 94 b = block_get(dev_handle, rscnt + fsec, bps); 95 clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); 96 assert(clst != FAT_CLST_BAD); 97 assert(clst < FAT_CLST_LAST1); 98 block_put(b); 99 } 100 101 b = block_get(dev_handle, ssa + (clst - FAT_CLST_FIRST) * spc + 102 offset % spc, bps); 103 104 return b; 105 } 106 107 /** Return number of blocks allocated to a file. 108 * 109 * @param dev_handle Device handle of the device with the file. 110 * @param firstc First cluster of the file. 111 * 112 * @return Number of blocks allocated to the file. 113 */ 114 uint16_t 115 _fat_blcks_get(dev_handle_t dev_handle, fat_cluster_t firstc) 116 { 117 block_t *bb; 118 block_t *b; 119 unsigned bps; 120 unsigned spc; 121 unsigned rscnt; /* block address of the first FAT */ 122 unsigned clusters = 0; 123 fat_cluster_t clst = firstc; 124 125 bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); 126 bps = uint16_t_le2host(FAT_BS(bb)->bps); 127 spc = FAT_BS(bb)->spc; 128 rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt); 129 block_put(bb); 130 131 if (firstc == FAT_CLST_RES0) { 132 /* No space allocated to the file. */ 133 return 0; 134 } 135 136 while (clst < FAT_CLST_LAST1) { 137 unsigned fsec; /* sector offset relative to FAT1 */ 138 unsigned fidx; /* FAT1 entry index */ 139 140 assert(clst >= FAT_CLST_FIRST); 141 fsec = (clst * sizeof(fat_cluster_t)) / bps; 142 fidx = clst % (bps / sizeof(fat_cluster_t)); 143 /* read FAT1 */ 144 b = block_get(dev_handle, rscnt + fsec, bps); 145 clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); 146 assert(clst != FAT_CLST_BAD); 147 block_put(b); 148 clusters++; 149 } 150 151 return clusters * spc; 152 } 153 154 uint16_t fat_bps_get(dev_handle_t dev_handle) 155 { 156 block_t *bb; 157 uint16_t bps; 158 159 bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); 160 assert(bb != NULL); 161 bps = uint16_t_le2host(FAT_BS(bb)->bps); 162 block_put(bb); 163 164 return bps; 165 } 166 167 /** Fill the gap between EOF and a new file position. 168 * 169 * @param nodep FAT node with the gap. 170 * @param mcl First cluster in an independent cluster chain that will 171 * be later appended to the end of the node's own cluster 172 * chain. If pos is still in the last allocated cluster, 173 * this argument is ignored. 174 * @param pos Position in the last node block. 175 */ 176 void fat_fill_gap(fat_node_t *nodep, fat_cluster_t mcl, off_t pos) 177 { 178 uint16_t bps; 179 unsigned spc; 180 block_t *bb, *b; 181 off_t o, boundary; 182 183 bb = block_get(nodep->idx->dev_handle, BS_BLOCK, BS_SIZE); 184 bps = uint16_t_le2host(FAT_BS(bb)->bps); 185 spc = FAT_BS(bb)->spc; 186 block_put(bb); 187 188 boundary = ROUND_UP(nodep->size, bps * spc); 189 190 /* zero out already allocated space */ 191 for (o = nodep->size - 1; o < pos && o < boundary; 192 o = ALIGN_DOWN(o + bps, bps)) { 193 b = fat_block_get(nodep, o / bps); 194 memset(b->data + o % bps, 0, bps - o % bps); 195 b->dirty = true; /* need to sync node */ 196 block_put(b); 197 } 198 199 if (o >= pos) 200 return; 201 202 /* zero out the initial part of the new cluster chain */ 203 for (o = boundary; o < pos; o += bps) { 204 b = _fat_block_get(nodep->idx->dev_handle, mcl, 205 (o - boundary) / bps); 206 memset(b->data, 0, min(bps, pos - o)); 207 b->dirty = true; /* need to sync node */ 208 block_put(b); 209 } 210 } 211 212 void 213 fat_mark_cluster(dev_handle_t dev_handle, unsigned fatno, fat_cluster_t clst, 214 fat_cluster_t value) 215 { 216 /* TODO */ 217 } 218 219 void 220 fat_alloc_shadow_clusters(dev_handle_t dev_handle, fat_cluster_t *lifo, 221 unsigned nclsts) 222 { 223 /* TODO */ 224 } 225 226 int 227 fat_alloc_clusters(dev_handle_t dev_handle, unsigned nclsts, fat_cluster_t *mcl, 228 fat_cluster_t *lcl) 229 { 230 uint16_t bps; 231 uint16_t rscnt; 232 uint16_t sf; 233 block_t *bb, *blk; 234 fat_cluster_t *lifo; /* stack for storing free cluster numbers */ 235 unsigned found = 0; /* top of the free cluster number stack */ 236 unsigned b, c, cl; 237 238 lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t)); 239 if (lifo) 240 return ENOMEM; 241 242 bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); 243 bps = uint16_t_le2host(FAT_BS(bb)->bps); 244 rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt); 245 sf = uint16_t_le2host(FAT_BS(bb)->sec_per_fat); 246 block_put(bb); 247 248 /* 249 * Search FAT1 for unused clusters. 250 */ 251 for (b = 0, cl = 0; b < sf; blk++) { 252 blk = block_get(dev_handle, rscnt + b, bps); 253 for (c = 0; c < bps / sizeof(fat_cluster_t); c++, cl++) { 254 fat_cluster_t *clst = (fat_cluster_t *)blk->data + c; 255 if (*clst == FAT_CLST_RES0) { 256 /* 257 * The cluster is free. Put it into our stack 258 * of found clusters and mark it as non-free. 259 */ 260 lifo[found] = cl; 261 if (found == 0) 262 *clst = FAT_CLST_LAST1; 263 else 264 *clst = lifo[found - 1]; 265 blk->dirty = true; /* need to sync block */ 266 if (++found == nclsts) { 267 /* we are almost done */ 268 block_put(blk); 269 /* update the shadow copies of FAT */ 270 fat_alloc_shadow_clusters(dev_handle, 271 lifo, nclsts); 272 *mcl = lifo[found - 1]; 273 *lcl = lifo[0]; 274 free(lifo); 275 return EOK; 276 } 277 } 278 } 279 block_put(blk); 280 } 281 282 /* 283 * We could not find enough clusters. Now we need to free the clusters 284 * we have allocated so far. 285 */ 286 while (found--) 287 fat_mark_cluster(dev_handle, FAT1, lifo[found], FAT_CLST_RES0); 288 289 free(lifo); 290 return ENOSPC; 291 } 292 293 void fat_append_clusters(fat_node_t *nodep, fat_cluster_t mcl) 294 { 295 } 38 296 39 297 /** -
uspace/srv/fs/fat/fat_fat.h
r033ef7d3 r0f57d0e 34 34 #define FAT_FAT_FAT_H_ 35 35 36 #include "../../vfs/vfs.h" 37 #include <stdint.h> 38 39 #define FAT1 0 40 41 #define FAT_CLST_RES0 0x0000 42 #define FAT_CLST_RES1 0x0001 43 #define FAT_CLST_FIRST 0x0002 44 #define FAT_CLST_BAD 0xfff7 45 #define FAT_CLST_LAST1 0xfff8 46 #define FAT_CLST_LAST8 0xffff 47 48 /* internally used to mark root directory's parent */ 49 #define FAT_CLST_ROOTPAR FAT_CLST_RES0 50 /* internally used to mark root directory */ 51 #define FAT_CLST_ROOT FAT_CLST_RES1 52 53 54 /* forward declarations */ 55 struct block; 56 struct fat_node; 57 58 typedef uint16_t fat_cluster_t; 59 60 #define fat_block_get(np, off) \ 61 _fat_block_get((np)->idx->dev_handle, (np)->firstc, (off)) 62 63 extern struct block *_fat_block_get(dev_handle_t, fat_cluster_t, off_t); 64 extern uint16_t _fat_blcks_get(dev_handle_t, fat_cluster_t); 65 extern uint16_t fat_bps_get(dev_handle_t); 66 67 extern void fat_append_clusters(struct fat_node *, fat_cluster_t); 68 extern int fat_alloc_clusters(dev_handle_t, unsigned, fat_cluster_t *, 69 fat_cluster_t *); 70 extern void fat_alloc_shadow_clusters(dev_handle_t, fat_cluster_t *, unsigned); 71 extern void fat_mark_cluster(dev_handle_t, unsigned, fat_cluster_t, 72 fat_cluster_t); 73 extern void fat_fill_gap(struct fat_node *, fat_cluster_t, off_t); 74 36 75 #endif 37 76 -
uspace/srv/fs/fat/fat_ops.c
r033ef7d3 r0f57d0e 55 55 #include <align.h> 56 56 57 #define BS_BLOCK 058 #define BS_SIZE 51259 60 57 /** Futex protecting the list of cached free FAT nodes. */ 61 58 static futex_t ffn_futex = FUTEX_INITIALIZER; … … 64 61 static LIST_INITIALIZE(ffn_head); 65 62 66 #define min(a, b) ((a) < (b) ? (a) : (b))67 68 63 static int dev_phone = -1; /* FIXME */ 69 64 static void *dev_buffer = NULL; /* FIXME */ 70 65 71 /* TODO move somewhere else */ 72 typedef struct { 73 void *data; 74 size_t size; 75 bool dirty; 76 } block_t; 77 78 static block_t *block_get(dev_handle_t dev_handle, off_t offset, size_t bs) 66 block_t *block_get(dev_handle_t dev_handle, off_t offset, size_t bs) 79 67 { 80 68 /* FIXME */ … … 108 96 } 109 97 110 staticvoid block_put(block_t *block)98 void block_put(block_t *block) 111 99 { 112 100 /* FIXME */ 113 101 free(block->data); 114 102 free(block); 115 }116 117 #define FAT1 0118 119 #define FAT_BS(b) ((fat_bs_t *)((b)->data))120 121 #define FAT_CLST_RES0 0x0000122 #define FAT_CLST_RES1 0x0001123 #define FAT_CLST_FIRST 0x0002124 #define FAT_CLST_BAD 0xfff7125 #define FAT_CLST_LAST1 0xfff8126 #define FAT_CLST_LAST8 0xffff127 128 /* internally used to mark root directory's parent */129 #define FAT_CLST_ROOTPAR FAT_CLST_RES0130 /* internally used to mark root directory */131 #define FAT_CLST_ROOT FAT_CLST_RES1132 133 #define fat_block_get(np, off) \134 _fat_block_get((np)->idx->dev_handle, (np)->firstc, (off))135 136 static block_t *137 _fat_block_get(dev_handle_t dev_handle, fat_cluster_t firstc, off_t offset)138 {139 block_t *bb;140 block_t *b;141 unsigned bps;142 unsigned spc;143 unsigned rscnt; /* block address of the first FAT */144 unsigned fatcnt;145 unsigned rde;146 unsigned rds; /* root directory size */147 unsigned sf;148 unsigned ssa; /* size of the system area */149 unsigned clusters;150 fat_cluster_t clst = firstc;151 unsigned i;152 153 bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);154 bps = uint16_t_le2host(FAT_BS(bb)->bps);155 spc = FAT_BS(bb)->spc;156 rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt);157 fatcnt = FAT_BS(bb)->fatcnt;158 rde = uint16_t_le2host(FAT_BS(bb)->root_ent_max);159 sf = uint16_t_le2host(FAT_BS(bb)->sec_per_fat);160 block_put(bb);161 162 rds = (sizeof(fat_dentry_t) * rde) / bps;163 rds += ((sizeof(fat_dentry_t) * rde) % bps != 0);164 ssa = rscnt + fatcnt * sf + rds;165 166 if (firstc == FAT_CLST_ROOT) {167 /* root directory special case */168 assert(offset < rds);169 b = block_get(dev_handle, rscnt + fatcnt * sf + offset, bps);170 return b;171 }172 173 clusters = offset / spc;174 for (i = 0; i < clusters; i++) {175 unsigned fsec; /* sector offset relative to FAT1 */176 unsigned fidx; /* FAT1 entry index */177 178 assert(clst >= FAT_CLST_FIRST && clst < FAT_CLST_BAD);179 fsec = (clst * sizeof(fat_cluster_t)) / bps;180 fidx = clst % (bps / sizeof(fat_cluster_t));181 /* read FAT1 */182 b = block_get(dev_handle, rscnt + fsec, bps);183 clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);184 assert(clst != FAT_CLST_BAD);185 assert(clst < FAT_CLST_LAST1);186 block_put(b);187 }188 189 b = block_get(dev_handle, ssa + (clst - FAT_CLST_FIRST) * spc +190 offset % spc, bps);191 192 return b;193 }194 195 /** Return number of blocks allocated to a file.196 *197 * @param dev_handle Device handle of the device with the file.198 * @param firstc First cluster of the file.199 *200 * @return Number of blocks allocated to the file.201 */202 static uint16_t203 _fat_blcks_get(dev_handle_t dev_handle, fat_cluster_t firstc)204 {205 block_t *bb;206 block_t *b;207 unsigned bps;208 unsigned spc;209 unsigned rscnt; /* block address of the first FAT */210 unsigned clusters = 0;211 fat_cluster_t clst = firstc;212 213 bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);214 bps = uint16_t_le2host(FAT_BS(bb)->bps);215 spc = FAT_BS(bb)->spc;216 rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt);217 block_put(bb);218 219 if (firstc == FAT_CLST_RES0) {220 /* No space allocated to the file. */221 return 0;222 }223 224 while (clst < FAT_CLST_LAST1) {225 unsigned fsec; /* sector offset relative to FAT1 */226 unsigned fidx; /* FAT1 entry index */227 228 assert(clst >= FAT_CLST_FIRST);229 fsec = (clst * sizeof(fat_cluster_t)) / bps;230 fidx = clst % (bps / sizeof(fat_cluster_t));231 /* read FAT1 */232 b = block_get(dev_handle, rscnt + fsec, bps);233 clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);234 assert(clst != FAT_CLST_BAD);235 block_put(b);236 clusters++;237 }238 239 return clusters * spc;240 103 } 241 104 … … 250 113 node->refcnt = 0; 251 114 node->dirty = false; 252 }253 254 static uint16_t fat_bps_get(dev_handle_t dev_handle)255 {256 block_t *bb;257 uint16_t bps;258 259 bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);260 assert(bb != NULL);261 bps = uint16_t_le2host(FAT_BS(bb)->bps);262 block_put(bb);263 264 return bps;265 115 } 266 116 … … 787 637 } 788 638 789 /** Fill the gap between EOF and a new file position.790 *791 * @param nodep FAT node with the gap.792 * @param mcl First cluster in an independent cluster chain that will793 * be later appended to the end of the node's own cluster794 * chain. If pos is still in the last allocated cluster,795 * this argument is ignored.796 * @param pos Position in the last node block.797 */798 static void799 fat_fill_gap(fat_node_t *nodep, fat_cluster_t mcl, off_t pos)800 {801 uint16_t bps;802 unsigned spc;803 block_t *bb, *b;804 off_t o, boundary;805 806 bb = block_get(nodep->idx->dev_handle, BS_BLOCK, BS_SIZE);807 bps = uint16_t_le2host(FAT_BS(bb)->bps);808 spc = FAT_BS(bb)->spc;809 block_put(bb);810 811 boundary = ROUND_UP(nodep->size, bps * spc);812 813 /* zero out already allocated space */814 for (o = nodep->size - 1; o < pos && o < boundary;815 o = ALIGN_DOWN(o + bps, bps)) {816 b = fat_block_get(nodep, o / bps);817 memset(b->data + o % bps, 0, bps - o % bps);818 b->dirty = true; /* need to sync node */819 block_put(b);820 }821 822 if (o >= pos)823 return;824 825 /* zero out the initial part of the new cluster chain */826 for (o = boundary; o < pos; o += bps) {827 b = _fat_block_get(nodep->idx->dev_handle, mcl,828 (o - boundary) / bps);829 memset(b->data, 0, min(bps, pos - o));830 b->dirty = true; /* need to sync node */831 block_put(b);832 }833 }834 835 static void836 fat_mark_cluster(dev_handle_t dev_handle, unsigned fatno, fat_cluster_t clst,837 fat_cluster_t value)838 {839 /* TODO */840 }841 842 static void843 fat_alloc_shadow_clusters(dev_handle_t dev_handle, fat_cluster_t *lifo,844 unsigned nclsts)845 {846 /* TODO */847 }848 849 static int850 fat_alloc_clusters(dev_handle_t dev_handle, unsigned nclsts, fat_cluster_t *mcl,851 fat_cluster_t *lcl)852 {853 uint16_t bps;854 uint16_t rscnt;855 uint16_t sf;856 block_t *bb, *blk;857 fat_cluster_t *lifo; /* stack for storing free cluster numbers */858 unsigned found = 0; /* top of the free cluster number stack */859 unsigned b, c, cl;860 861 lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));862 if (lifo)863 return ENOMEM;864 865 bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);866 bps = uint16_t_le2host(FAT_BS(bb)->bps);867 rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt);868 sf = uint16_t_le2host(FAT_BS(bb)->sec_per_fat);869 block_put(bb);870 871 /*872 * Search FAT1 for unused clusters.873 */874 for (b = 0, cl = 0; b < sf; blk++) {875 blk = block_get(dev_handle, rscnt + b, bps);876 for (c = 0; c < bps / sizeof(fat_cluster_t); c++, cl++) {877 fat_cluster_t *clst = (fat_cluster_t *)blk->data + c;878 if (*clst == FAT_CLST_RES0) {879 /*880 * The cluster is free. Put it into our stack881 * of found clusters and mark it as non-free.882 */883 lifo[found] = cl;884 if (found == 0)885 *clst = FAT_CLST_LAST1;886 else887 *clst = lifo[found - 1];888 blk->dirty = true; /* need to sync block */889 if (++found == nclsts) {890 /* we are almost done */891 block_put(blk);892 /* update the shadow copies of FAT */893 fat_alloc_shadow_clusters(dev_handle,894 lifo, nclsts);895 *mcl = lifo[found - 1];896 *lcl = lifo[0];897 free(lifo);898 return EOK;899 }900 }901 }902 block_put(blk);903 }904 905 /*906 * We could not find enough clusters. Now we need to free the clusters907 * we have allocated so far.908 */909 while (found--)910 fat_mark_cluster(dev_handle, FAT1, lifo[found], FAT_CLST_RES0);911 912 free(lifo);913 return ENOSPC;914 }915 916 static void917 fat_append_clusters(fat_node_t *nodep, fat_cluster_t mcl)918 {919 }920 921 639 void fat_write(ipc_callid_t rid, ipc_call_t *request) 922 640 {
Note:
See TracChangeset
for help on using the changeset viewer.