Changeset 4c3c4a5 in mainline
- Timestamp:
- 2011-06-29T04:04:19Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 2fb88ea
- Parents:
- fcc3cd8
- Location:
- uspace/srv/fs/exfat
- Files:
-
- 3 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/exfat/Makefile
rfcc3cd8 r4c3c4a5 35 35 SOURCES = \ 36 36 exfat.c \ 37 exfat_fat.c \ 37 38 exfat_ops.c \ 39 exfat_idx.c 38 40 39 41 include $(USPACE_PREFIX)/Makefile.common -
uspace/srv/fs/exfat/exfat.c
rfcc3cd8 r4c3c4a5 158 158 159 159 printf(NAME ": HelenOS exFAT file system server\n"); 160 /* 160 161 161 rc = exfat_idx_init(); 162 162 if (rc != EOK) 163 163 goto err; 164 */ 164 165 165 vfs_phone = service_connect_blocking(SERVICE_VFS, 0, 0); 166 166 if (vfs_phone < EOK) { … … 171 171 rc = fs_register(vfs_phone, &exfat_reg, &exfat_vfs_info, exfat_connection); 172 172 if (rc != EOK) { 173 /* exfat_idx_fini(); */173 exfat_idx_fini(); 174 174 goto err; 175 175 } -
uspace/srv/fs/exfat/exfat.h
rfcc3cd8 r4c3c4a5 35 35 #define EXFAT_FAT_H_ 36 36 37 #include "exfat_fat.h" 37 38 #include <fibril_synch.h> 38 39 #include <libfs.h> … … 58 59 #define DATA_CNT(bs) uint32_t_le2host(bs->data_clusters) 59 60 #define ROOT_ST(bs) uint32_t_le2host(bs->rootdir_cluster) 60 #define VOL_FLAGS 61 #define VOL_FLAGS(bs) uint16_t_le2host(bs->volume_flags) 61 62 62 63 … … 88 89 } __attribute__((__packed__)) exfat_bs_t; 89 90 91 typedef enum { 92 EXFAT_DIRECTORY, 93 EXFAT_FILE 94 } exfat_node_type_t; 95 96 struct exfat_node; 97 98 typedef struct { 99 /** Used indices (position) hash table link. */ 100 link_t uph_link; 101 /** Used indices (index) hash table link. */ 102 link_t uih_link; 103 104 fibril_mutex_t lock; 105 devmap_handle_t devmap_handle; 106 fs_index_t index; 107 /** 108 * Parent node's first cluster. 109 * Zero is used if this node is not linked, in which case nodep must 110 * contain a pointer to the in-core node structure. 111 * One is used when the parent is the root directory. 112 */ 113 exfat_cluster_t pfc; 114 /** Directory entry index within the parent node. */ 115 unsigned pdi; 116 /** Pointer to in-core node instance. */ 117 struct exfat_node *nodep; 118 } exfat_idx_t; 119 120 /** exFAT in-core node. */ 121 typedef struct exfat_node { 122 /** Back pointer to the FS node. */ 123 fs_node_t *bp; 124 125 fibril_mutex_t lock; 126 exfat_node_type_t type; 127 exfat_idx_t *idx; 128 /** 129 * Node's first cluster. 130 * Zero is used for zero-length nodes. 131 * One is used to mark root directory. 132 */ 133 exfat_cluster_t firstc; 134 /** exFAT in-core node free list link. */ 135 link_t ffn_link; 136 aoff64_t size; 137 unsigned lnkcnt; 138 unsigned refcnt; 139 bool dirty; 140 141 /* 142 * Cache of the node's last and "current" cluster to avoid some 143 * unnecessary FAT walks. 144 */ 145 /* Node's last cluster in FAT. */ 146 bool lastc_cached_valid; 147 exfat_cluster_t lastc_cached_value; 148 /* Node's "current" cluster, i.e. where the last I/O took place. */ 149 bool currc_cached_valid; 150 aoff64_t currc_cached_bn; 151 exfat_cluster_t currc_cached_value; 152 } exfat_node_t; 153 90 154 91 155 extern fs_reg_t exfat_reg; … … 95 159 extern void exfat_unmounted(ipc_callid_t, ipc_call_t *); 96 160 extern void exfat_unmount(ipc_callid_t, ipc_call_t *); 161 extern void exfat_lookup(ipc_callid_t, ipc_call_t *); 162 extern void exfat_read(ipc_callid_t, ipc_call_t *); 163 extern void exfat_write(ipc_callid_t, ipc_call_t *); 164 extern void exfat_truncate(ipc_callid_t, ipc_call_t *); 165 extern void exfat_stat(ipc_callid_t, ipc_call_t *); 166 extern void exfat_close(ipc_callid_t, ipc_call_t *); 167 extern void exfat_destroy(ipc_callid_t, ipc_call_t *); 168 extern void exfat_open_node(ipc_callid_t, ipc_call_t *); 169 extern void exfat_stat(ipc_callid_t, ipc_call_t *); 170 extern void exfat_sync(ipc_callid_t, ipc_call_t *); 171 172 extern int exfat_idx_get_new(exfat_idx_t **, devmap_handle_t); 173 extern exfat_idx_t *exfat_idx_get_by_pos(devmap_handle_t, exfat_cluster_t, unsigned); 174 extern exfat_idx_t *exfat_idx_get_by_index(devmap_handle_t, fs_index_t); 175 extern void exfat_idx_destroy(exfat_idx_t *); 176 extern void exfat_idx_hashin(exfat_idx_t *); 177 extern void exfat_idx_hashout(exfat_idx_t *); 178 179 extern int exfat_idx_init(void); 180 extern void exfat_idx_fini(void); 181 extern int exfat_idx_init_by_devmap_handle(devmap_handle_t); 182 extern void exfat_idx_fini_by_devmap_handle(devmap_handle_t); 97 183 98 184 #endif -
uspace/srv/fs/exfat/exfat_ops.c
rfcc3cd8 r4c3c4a5 38 38 39 39 #include "exfat.h" 40 #include "exfat_fat.h" 40 41 #include "../../vfs/vfs.h" 41 42 #include <libfs.h> … … 55 56 #include <align.h> 56 57 #include <malloc.h> 58 #include <stdio.h> 59 60 #define EXFAT_NODE(node) ((node) ? (exfat_node_t *) (node)->data : NULL) 61 #define FS_NODE(node) ((node) ? (node)->bp : NULL) 62 63 64 /** Mutex protecting the list of cached free FAT nodes. */ 65 static FIBRIL_MUTEX_INITIALIZE(ffn_mutex); 66 67 /** List of cached free FAT nodes. */ 68 static LIST_INITIALIZE(ffn_head); 69 70 /* 71 * Forward declarations of FAT libfs operations. 72 */ 73 static int exfat_root_get(fs_node_t **, devmap_handle_t); 74 static int exfat_match(fs_node_t **, fs_node_t *, const char *); 75 static int exfat_node_get(fs_node_t **, devmap_handle_t, fs_index_t); 76 static int exfat_node_open(fs_node_t *); 77 static int exfat_node_put(fs_node_t *); 78 static int exfat_create_node(fs_node_t **, devmap_handle_t, int); 79 static int exfat_destroy_node(fs_node_t *); 80 static int exfat_link(fs_node_t *, fs_node_t *, const char *); 81 static int exfat_unlink(fs_node_t *, fs_node_t *, const char *); 82 static int exfat_has_children(bool *, fs_node_t *); 83 static fs_index_t exfat_index_get(fs_node_t *); 84 static aoff64_t exfat_size_get(fs_node_t *); 85 static unsigned exfat_lnkcnt_get(fs_node_t *); 86 static char exfat_plb_get_char(unsigned); 87 static bool exfat_is_directory(fs_node_t *); 88 static bool exfat_is_file(fs_node_t *node); 89 static devmap_handle_t exfat_device_get(fs_node_t *node); 90 91 /* 92 * Helper functions. 93 */ 94 static void exfat_node_initialize(exfat_node_t *node) 95 { 96 fibril_mutex_initialize(&node->lock); 97 node->bp = NULL; 98 node->idx = NULL; 99 node->type = 0; 100 link_initialize(&node->ffn_link); 101 node->size = 0; 102 node->lnkcnt = 0; 103 node->refcnt = 0; 104 node->dirty = false; 105 node->lastc_cached_valid = false; 106 node->lastc_cached_value = 0; 107 node->currc_cached_valid = false; 108 node->currc_cached_bn = 0; 109 node->currc_cached_value = 0; 110 } 111 112 static int exfat_node_sync(exfat_node_t *node) 113 { 114 return EOK; 115 } 116 117 static int exfat_node_fini_by_devmap_handle(devmap_handle_t devmap_handle) 118 { 119 link_t *lnk; 120 exfat_node_t *nodep; 121 int rc; 122 123 /* 124 * We are called from fat_unmounted() and assume that there are already 125 * no nodes belonging to this instance with non-zero refcount. Therefore 126 * it is sufficient to clean up only the FAT free node list. 127 */ 128 129 restart: 130 fibril_mutex_lock(&ffn_mutex); 131 for (lnk = ffn_head.next; lnk != &ffn_head; lnk = lnk->next) { 132 nodep = list_get_instance(lnk, exfat_node_t, ffn_link); 133 if (!fibril_mutex_trylock(&nodep->lock)) { 134 fibril_mutex_unlock(&ffn_mutex); 135 goto restart; 136 } 137 if (!fibril_mutex_trylock(&nodep->idx->lock)) { 138 fibril_mutex_unlock(&nodep->lock); 139 fibril_mutex_unlock(&ffn_mutex); 140 goto restart; 141 } 142 if (nodep->idx->devmap_handle != devmap_handle) { 143 fibril_mutex_unlock(&nodep->idx->lock); 144 fibril_mutex_unlock(&nodep->lock); 145 continue; 146 } 147 148 list_remove(&nodep->ffn_link); 149 fibril_mutex_unlock(&ffn_mutex); 150 151 /* 152 * We can unlock the node and its index structure because we are 153 * the last player on this playground and VFS is preventing new 154 * players from entering. 155 */ 156 fibril_mutex_unlock(&nodep->idx->lock); 157 fibril_mutex_unlock(&nodep->lock); 158 159 if (nodep->dirty) { 160 rc = exfat_node_sync(nodep); 161 if (rc != EOK) 162 return rc; 163 } 164 nodep->idx->nodep = NULL; 165 free(nodep->bp); 166 free(nodep); 167 168 /* Need to restart because we changed the ffn_head list. */ 169 goto restart; 170 } 171 fibril_mutex_unlock(&ffn_mutex); 172 173 return EOK; 174 } 175 176 177 /* 178 * FAT libfs operations. 179 */ 180 181 int exfat_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle) 182 { 183 return exfat_node_get(rfn, devmap_handle, 0); 184 } 185 186 int exfat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 187 { 188 *rfn = NULL; 189 return EOK; 190 } 191 192 /** Instantiate a exFAT in-core node. */ 193 int exfat_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index) 194 { 195 *rfn = NULL; 196 return EOK; 197 } 198 199 int exfat_node_open(fs_node_t *fn) 200 { 201 /* 202 * Opening a file is stateless, nothing 203 * to be done here. 204 */ 205 return EOK; 206 } 207 208 int exfat_node_put(fs_node_t *fn) 209 { 210 return EOK; 211 } 212 213 int exfat_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int flags) 214 { 215 *rfn = NULL; 216 return EOK; 217 } 218 219 int exfat_destroy_node(fs_node_t *fn) 220 { 221 return EOK; 222 } 223 224 int exfat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name) 225 { 226 return EOK; 227 } 228 229 int exfat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm) 230 { 231 return EOK; 232 } 233 234 int exfat_has_children(bool *has_children, fs_node_t *fn) 235 { 236 *has_children = false; 237 return EOK; 238 } 239 240 241 fs_index_t exfat_index_get(fs_node_t *fn) 242 { 243 return EXFAT_NODE(fn)->idx->index; 244 } 245 246 aoff64_t exfat_size_get(fs_node_t *fn) 247 { 248 return EXFAT_NODE(fn)->size; 249 } 250 251 unsigned exfat_lnkcnt_get(fs_node_t *fn) 252 { 253 return EXFAT_NODE(fn)->lnkcnt; 254 } 255 256 char exfat_plb_get_char(unsigned pos) 257 { 258 return exfat_reg.plb_ro[pos % PLB_SIZE]; 259 } 260 261 bool exfat_is_directory(fs_node_t *fn) 262 { 263 return EXFAT_NODE(fn)->type == EXFAT_DIRECTORY; 264 } 265 266 bool exfat_is_file(fs_node_t *fn) 267 { 268 return EXFAT_NODE(fn)->type == EXFAT_FILE; 269 } 270 271 devmap_handle_t exfat_device_get(fs_node_t *node) 272 { 273 return 0; 274 } 275 57 276 58 277 /** libfs operations */ 59 60 libfs_ops_t exfat_libfs_ops;61 /*62 278 libfs_ops_t exfat_libfs_ops = { 63 279 .root_get = exfat_root_get, … … 79 295 .device_get = exfat_device_get 80 296 }; 81 */ 297 82 298 83 299 /* … … 136 352 } 137 353 138 async_answer_0(rid, EOK); 139 /* async_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt); */ 354 /* Do some simple sanity checks on the file system. */ 355 rc = exfat_sanity_check(bs, devmap_handle); 356 if (rc != EOK) { 357 (void) block_cache_fini(devmap_handle); 358 block_fini(devmap_handle); 359 async_answer_0(rid, rc); 360 return; 361 } 362 363 rc = exfat_idx_init_by_devmap_handle(devmap_handle); 364 if (rc != EOK) { 365 (void) block_cache_fini(devmap_handle); 366 block_fini(devmap_handle); 367 async_answer_0(rid, rc); 368 return; 369 } 370 371 /* Initialize the root node. */ 372 fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t)); 373 if (!rfn) { 374 (void) block_cache_fini(devmap_handle); 375 block_fini(devmap_handle); 376 exfat_idx_fini_by_devmap_handle(devmap_handle); 377 async_answer_0(rid, ENOMEM); 378 return; 379 } 380 381 fs_node_initialize(rfn); 382 exfat_node_t *rootp = (exfat_node_t *)malloc(sizeof(exfat_node_t)); 383 if (!rootp) { 384 free(rfn); 385 (void) block_cache_fini(devmap_handle); 386 block_fini(devmap_handle); 387 exfat_idx_fini_by_devmap_handle(devmap_handle); 388 async_answer_0(rid, ENOMEM); 389 return; 390 } 391 392 exfat_node_initialize(rootp); 393 394 /* exfat_idx_t *ridxp = exfat_idx_get_by_pos(devmap_handle, FAT_CLST_ROOTPAR, 0); */ 395 exfat_idx_t *ridxp = exfat_idx_get_by_pos(devmap_handle, 0, 0); 396 if (!ridxp) { 397 free(rfn); 398 free(rootp); 399 (void) block_cache_fini(devmap_handle); 400 block_fini(devmap_handle); 401 exfat_idx_fini_by_devmap_handle(devmap_handle); 402 async_answer_0(rid, ENOMEM); 403 return; 404 } 405 assert(ridxp->index == 0); 406 /* ridxp->lock held */ 407 408 rootp->type = EXFAT_DIRECTORY; 409 rootp->firstc = ROOT_ST(bs); 410 rootp->refcnt = 1; 411 rootp->lnkcnt = 0; /* FS root is not linked */ 412 rootp->idx = ridxp; 413 ridxp->nodep = rootp; 414 rootp->bp = rfn; 415 rfn->data = rootp; 416 417 fibril_mutex_unlock(&ridxp->lock); 418 419 /* async_answer_0(rid, EOK); */ 420 async_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt); 140 421 } 141 422 … … 148 429 { 149 430 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 431 fs_node_t *fn; 432 exfat_node_t *nodep; 433 int rc; 434 435 rc = exfat_root_get(&fn, devmap_handle); 436 if (rc != EOK) { 437 async_answer_0(rid, rc); 438 return; 439 } 440 nodep = EXFAT_NODE(fn); 441 442 /* 443 * We expect exactly two references on the root node. One for the 444 * fat_root_get() above and one created in fat_mounted(). 445 */ 446 if (nodep->refcnt != 2) { 447 (void) exfat_node_put(fn); 448 async_answer_0(rid, EBUSY); 449 return; 450 } 451 452 /* 453 * Put the root node and force it to the FAT free node list. 454 */ 455 (void) exfat_node_put(fn); 456 (void) exfat_node_put(fn); 150 457 151 458 /* … … 154 461 * stop using libblock for this instance. 155 462 */ 463 (void) exfat_node_fini_by_devmap_handle(devmap_handle); 464 exfat_idx_fini_by_devmap_handle(devmap_handle); 156 465 (void) block_cache_fini(devmap_handle); 157 466 block_fini(devmap_handle);
Note:
See TracChangeset
for help on using the changeset viewer.