Changeset 8ff0bd2 in mainline for uspace/srv/fs
- Timestamp:
- 2011-09-04T11:30:58Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 03bc76a
- Parents:
- d2c67e7 (diff), deac215e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- uspace/srv/fs
- Files:
-
- 15 added
- 1 deleted
- 16 edited
- 5 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/exfat/exfat.c
rd2c67e7 r8ff0bd2 1 1 /* 2 * Copyright (c) 2011 Vojtech Horky 2 * Copyright (c) 2006 Martin Decky 3 * Copyright (c) 2008 Jakub Jermar 4 * Copyright (c) 2011 Oleg Romanenko 3 5 * All rights reserved. 4 6 * … … 27 29 */ 28 30 29 /** @addtogroup tester 30 * @brief Test devman service. 31 /** @addtogroup fs 31 32 * @{ 32 */ 33 */ 34 33 35 /** 34 * @file 36 * @file exfat.c 37 * @brief FAT file system driver for HelenOS. 35 38 */ 36 39 37 #include <inttypes.h> 40 #include "exfat.h" 41 #include <ipc/services.h> 42 #include <ns.h> 43 #include <async.h> 38 44 #include <errno.h> 39 #include <str_error.h> 40 #include <sys/types.h> 41 #include <async.h> 42 #include <devman.h> 43 #include <str.h> 44 #include <async.h> 45 #include <vfs/vfs.h> 46 #include <vfs/vfs_sess.h> 47 #include <sys/stat.h> 48 #include <fcntl.h> 49 #include "../tester.h" 45 #include <unistd.h> 46 #include <task.h> 47 #include <stdio.h> 48 #include <libfs.h> 49 #include "../../vfs/vfs.h" 50 50 51 #define DEVICE_CLASS "test3"51 #define NAME "exfat" 52 52 53 const char *test_devman2(void) 53 vfs_info_t exfat_vfs_info = { 54 .name = NAME, 55 .concurrent_read_write = false, 56 .write_retains_size = false, 57 }; 58 59 int main(int argc, char **argv) 54 60 { 55 size_t idx = 1; 56 int rc = EOK; 57 const char *err_msg = NULL; 58 char *path = NULL; 59 while (rc == EOK) { 60 rc = asprintf(&path, "/dev/class/%s\\%zu", DEVICE_CLASS, idx); 61 if (rc < 0) { 62 continue; 63 } 64 int fd = open(path, O_RDONLY); 65 if (fd < 0) { 66 TPRINTF("Failed opening `%s': %s.\n", 67 path, str_error(fd)); 68 rc = fd; 69 err_msg = "Failed opening file"; 70 continue; 71 } 72 async_sess_t *sess = fd_session(EXCHANGE_SERIALIZE, fd); 73 close(fd); 74 if (sess == NULL) { 75 TPRINTF("Failed opening phone: %s.\n", str_error(errno)); 76 rc = errno; 77 err_msg = "Failed opening file descriptor phone"; 78 continue; 79 } 80 async_hangup(sess); 81 TPRINTF("Path `%s' okay.\n", path); 82 free(path); 83 idx++; 84 rc = EOK; 61 printf(NAME ": HelenOS exFAT file system server\n"); 62 63 int rc = exfat_idx_init(); 64 if (rc != EOK) 65 goto err; 66 67 async_sess_t *vfs_sess = service_connect_blocking(EXCHANGE_SERIALIZE, 68 SERVICE_VFS, 0, 0); 69 if (!vfs_sess) { 70 printf(NAME ": failed to connect to VFS\n"); 71 return -1; 85 72 } 86 73 87 if (path != NULL) 88 free(path); 74 rc = fs_register(vfs_sess, &exfat_vfs_info, &exfat_ops, &exfat_libfs_ops); 75 if (rc != EOK) { 76 exfat_idx_fini(); 77 goto err; 78 } 89 79 90 return err_msg; 80 printf(NAME ": Accepting connections\n"); 81 task_retval(0); 82 async_manager(); 83 84 /* not reached */ 85 return 0; 86 87 err: 88 printf(NAME ": Failed to register file system (%d)\n", rc); 89 return rc; 91 90 } 92 91 93 /** @} 92 93 /** 94 * @} 94 95 */ -
uspace/srv/fs/exfat/exfat_bitmap.h
rd2c67e7 r8ff0bd2 1 1 /* 2 * Copyright (c) 20 09 Martin Decky2 * Copyright (c) 2011 Oleg Romanenko 3 3 * All rights reserved. 4 4 * … … 31 31 */ 32 32 33 #ifndef DEVFS_DEVFS_OPS_H_34 #define DEVFS_DEVFS_OPS_H_33 #ifndef EXFAT_EXFAT_BITMAP_H_ 34 #define EXFAT_EXFAT_BITMAP_H_ 35 35 36 #include <ipc/common.h> 37 #include <bool.h> 36 #include <stdint.h> 37 #include "exfat.h" 38 #include "exfat_fat.h" 38 39 39 extern bool devfs_init(void); 40 /* forward declarations */ 41 struct exfat_node; 42 struct exfat_bs; 40 43 41 extern void devfs_mounted(ipc_callid_t, ipc_call_t *); 42 extern void devfs_mount(ipc_callid_t, ipc_call_t *); 43 extern void devfs_unmounted(ipc_callid_t, ipc_call_t *); 44 extern void devfs_unmount(ipc_callid_t, ipc_call_t *); 45 extern void devfs_lookup(ipc_callid_t, ipc_call_t *); 46 extern void devfs_open_node(ipc_callid_t, ipc_call_t *); 47 extern void devfs_stat(ipc_callid_t, ipc_call_t *); 48 extern void devfs_sync(ipc_callid_t, ipc_call_t *); 49 extern void devfs_read(ipc_callid_t, ipc_call_t *); 50 extern void devfs_write(ipc_callid_t, ipc_call_t *); 51 extern void devfs_truncate(ipc_callid_t, ipc_call_t *); 52 extern void devfs_close(ipc_callid_t, ipc_call_t *); 53 extern void devfs_destroy(ipc_callid_t, ipc_call_t *); 44 extern int bitmap_alloc_clusters(struct exfat_bs *, service_id_t, 45 exfat_cluster_t *, exfat_cluster_t); 46 extern int bitmap_append_clusters(struct exfat_bs *, struct exfat_node *, 47 exfat_cluster_t); 48 extern int bitmap_free_clusters(struct exfat_bs *, struct exfat_node *, 49 exfat_cluster_t); 50 extern int bitmap_replicate_clusters(struct exfat_bs *, struct exfat_node *); 51 52 extern int bitmap_is_free(struct exfat_bs *, service_id_t, exfat_cluster_t); 53 extern int bitmap_set_cluster(struct exfat_bs *, service_id_t, exfat_cluster_t); 54 extern int bitmap_clear_cluster(struct exfat_bs *, service_id_t, 55 exfat_cluster_t); 56 57 extern int bitmap_set_clusters(struct exfat_bs *, service_id_t, 58 exfat_cluster_t, exfat_cluster_t); 59 extern int bitmap_clear_clusters(struct exfat_bs *, service_id_t, 60 exfat_cluster_t, exfat_cluster_t); 61 54 62 55 63 #endif -
uspace/srv/fs/ext2fs/ext2fs.c
rd2c67e7 r8ff0bd2 1 1 /* 2 2 * Copyright (c) 2006 Martin Decky 3 * Copyright (c) 2008 Jakub Jermar4 3 * Copyright (c) 2011 Martin Sucha 5 4 * All rights reserved. … … 55 54 }; 56 55 57 fs_reg_t ext2fs_reg;58 59 /**60 * This connection fibril processes VFS requests from VFS.61 *62 * In order to support simultaneous VFS requests, our design is as follows.63 * The connection fibril accepts VFS requests from VFS. If there is only one64 * instance of the fibril, VFS will need to serialize all VFS requests it sends65 * to EXT2FS. To overcome this bottleneck, VFS can send EXT2FS the IPC_M_CONNECT_ME_TO66 * call. In that case, a new connection fibril will be created, which in turn67 * will accept the call. Thus, a new phone will be opened for VFS.68 *69 * There are few issues with this arrangement. First, VFS can run out of70 * available phones. In that case, VFS can close some other phones or use one71 * phone for more serialized requests. Similarily, EXT2FS can refuse to duplicate72 * the connection. VFS should then just make use of already existing phones and73 * route its requests through them. To avoid paying the fibril creation price74 * upon each request, EXT2FS might want to keep the connections open after the75 * request has been completed.76 */77 static void ext2fs_connection(ipc_callid_t iid, ipc_call_t *icall)78 {79 if (iid) {80 /*81 * This only happens for connections opened by82 * IPC_M_CONNECT_ME_TO calls as opposed to callback connections83 * created by IPC_M_CONNECT_TO_ME.84 */85 async_answer_0(iid, EOK);86 }87 88 dprintf(NAME ": connection opened\n");89 while (true) {90 ipc_call_t call;91 ipc_callid_t callid = async_get_call(&call);92 93 if (!IPC_GET_IMETHOD(call))94 return;95 96 switch (IPC_GET_IMETHOD(call)) {97 case VFS_OUT_MOUNTED:98 ext2fs_mounted(callid, &call);99 break;100 case VFS_OUT_MOUNT:101 ext2fs_mount(callid, &call);102 break;103 case VFS_OUT_UNMOUNTED:104 ext2fs_unmounted(callid, &call);105 break;106 case VFS_OUT_UNMOUNT:107 ext2fs_unmount(callid, &call);108 break;109 case VFS_OUT_LOOKUP:110 ext2fs_lookup(callid, &call);111 break;112 case VFS_OUT_READ:113 ext2fs_read(callid, &call);114 break;115 case VFS_OUT_WRITE:116 ext2fs_write(callid, &call);117 break;118 case VFS_OUT_TRUNCATE:119 ext2fs_truncate(callid, &call);120 break;121 case VFS_OUT_STAT:122 ext2fs_stat(callid, &call);123 break;124 case VFS_OUT_CLOSE:125 ext2fs_close(callid, &call);126 break;127 case VFS_OUT_DESTROY:128 ext2fs_destroy(callid, &call);129 break;130 case VFS_OUT_OPEN_NODE:131 ext2fs_open_node(callid, &call);132 break;133 case VFS_OUT_SYNC:134 ext2fs_sync(callid, &call);135 break;136 default:137 async_answer_0(callid, ENOTSUP);138 break;139 }140 }141 }142 143 56 int main(int argc, char **argv) 144 57 { … … 158 71 } 159 72 160 rc = fs_register(vfs_sess, &ext2fs_reg, &ext2fs_vfs_info, ext2fs_connection); 73 rc = fs_register(vfs_sess, &ext2fs_vfs_info, &ext2fs_ops, 74 &ext2fs_libfs_ops); 161 75 if (rc != EOK) { 162 76 fprintf(stdout, NAME ": Failed to register fs (%d)\n", rc); -
uspace/srv/fs/ext2fs/ext2fs.h
rd2c67e7 r8ff0bd2 1 1 /* 2 * Copyright (c) 2008 Jakub Jermar3 2 * Copyright (c) 2011 Martin Sucha 4 3 * All rights reserved. … … 36 35 37 36 #include <libext2.h> 38 #include <fibril_synch.h>39 37 #include <libfs.h> 40 #include <atomic.h>41 38 #include <sys/types.h> 42 #include <bool.h>43 #include "../../vfs/vfs.h"44 45 #ifndef dprintf46 #define dprintf(...) printf(__VA_ARGS__)47 #endif48 39 49 40 #define min(a, b) ((a) < (b) ? (a) : (b)) 50 41 51 extern fs_reg_t ext2fs_reg; 42 extern vfs_out_ops_t ext2fs_ops; 43 extern libfs_ops_t ext2fs_libfs_ops; 52 44 53 45 extern int ext2fs_global_init(void); 54 46 extern int ext2fs_global_fini(void); 55 extern void ext2fs_mounted(ipc_callid_t, ipc_call_t *);56 extern void ext2fs_mount(ipc_callid_t, ipc_call_t *);57 extern void ext2fs_unmounted(ipc_callid_t, ipc_call_t *);58 extern void ext2fs_unmount(ipc_callid_t, ipc_call_t *);59 extern void ext2fs_lookup(ipc_callid_t, ipc_call_t *);60 extern void ext2fs_read(ipc_callid_t, ipc_call_t *);61 extern void ext2fs_write(ipc_callid_t, ipc_call_t *);62 extern void ext2fs_truncate(ipc_callid_t, ipc_call_t *);63 extern void ext2fs_stat(ipc_callid_t, ipc_call_t *);64 extern void ext2fs_close(ipc_callid_t, ipc_call_t *);65 extern void ext2fs_destroy(ipc_callid_t, ipc_call_t *);66 extern void ext2fs_open_node(ipc_callid_t, ipc_call_t *);67 extern void ext2fs_stat(ipc_callid_t, ipc_call_t *);68 extern void ext2fs_sync(ipc_callid_t, ipc_call_t *);69 47 70 48 #endif -
uspace/srv/fs/ext2fs/ext2fs_ops.c
rd2c67e7 r8ff0bd2 1 1 /* 2 * Copyright (c) 2008 Jakub Jermar3 2 * Copyright (c) 2011 Martin Sucha 4 3 * All rights reserved. … … 43 42 #include <libext2.h> 44 43 #include <ipc/services.h> 45 #include <ipc/ devmap.h>44 #include <ipc/loc.h> 46 45 #include <macros.h> 47 46 #include <async.h> … … 70 69 typedef struct ext2fs_instance { 71 70 link_t link; 72 devmap_handle_t devmap_handle;71 service_id_t service_id; 73 72 ext2_filesystem_t *filesystem; 74 73 unsigned int open_nodes_count; … … 86 85 * Forward declarations of auxiliary functions 87 86 */ 88 static int ext2fs_instance_get( devmap_handle_t, ext2fs_instance_t **);89 static void ext2fs_read_directory(ipc_callid_t, ipc_callid_t, aoff64_t,90 size_t, ext2fs_instance_t *, ext2_inode_ref_t *);91 static void ext2fs_read_file(ipc_callid_t, ipc_callid_t, aoff64_t,92 size_t, ext2fs_instance_t *, ext2_inode_ref_t *);87 static int ext2fs_instance_get(service_id_t, ext2fs_instance_t **); 88 static int ext2fs_read_directory(ipc_callid_t, aoff64_t, size_t, 89 ext2fs_instance_t *, ext2_inode_ref_t *, size_t *); 90 static int ext2fs_read_file(ipc_callid_t, aoff64_t, size_t, ext2fs_instance_t *, 91 ext2_inode_ref_t *, size_t *); 93 92 static bool ext2fs_is_dots(const uint8_t *, size_t); 94 93 static int ext2fs_node_get_core(fs_node_t **, ext2fs_instance_t *, fs_index_t); … … 98 97 * Forward declarations of EXT2 libfs operations. 99 98 */ 100 static int ext2fs_root_get(fs_node_t **, devmap_handle_t);99 static int ext2fs_root_get(fs_node_t **, service_id_t); 101 100 static int ext2fs_match(fs_node_t **, fs_node_t *, const char *); 102 static int ext2fs_node_get(fs_node_t **, devmap_handle_t, fs_index_t);101 static int ext2fs_node_get(fs_node_t **, service_id_t, fs_index_t); 103 102 static int ext2fs_node_open(fs_node_t *); 104 103 static int ext2fs_node_put(fs_node_t *); 105 static int ext2fs_create_node(fs_node_t **, devmap_handle_t, int);104 static int ext2fs_create_node(fs_node_t **, service_id_t, int); 106 105 static int ext2fs_destroy_node(fs_node_t *); 107 106 static int ext2fs_link(fs_node_t *, fs_node_t *, const char *); … … 111 110 static aoff64_t ext2fs_size_get(fs_node_t *); 112 111 static unsigned ext2fs_lnkcnt_get(fs_node_t *); 113 static char ext2fs_plb_get_char(unsigned);114 112 static bool ext2fs_is_directory(fs_node_t *); 115 113 static bool ext2fs_is_file(fs_node_t *node); 116 static devmap_handle_t ext2fs_device_get(fs_node_t *node);114 static service_id_t ext2fs_device_get(fs_node_t *node); 117 115 118 116 /* … … 136 134 ext2fs_node_t *enode = hash_table_get_instance(item, ext2fs_node_t, link); 137 135 assert(keys > 0); 138 if (enode->instance-> devmap_handle!=139 (( devmap_handle_t) key[OPEN_NODES_DEV_HANDLE_KEY])) {136 if (enode->instance->service_id != 137 ((service_id_t) key[OPEN_NODES_DEV_HANDLE_KEY])) { 140 138 return false; 141 139 } … … 182 180 183 181 /** 184 * Find an instance of filesystem for the given devmap_handle 185 */ 186 int ext2fs_instance_get(devmap_handle_t devmap_handle, ext2fs_instance_t **inst) 187 { 188 EXT2FS_DBG("(%" PRIun ", -)", devmap_handle); 189 link_t *link; 182 * Find an instance of filesystem for the given service_id 183 */ 184 int ext2fs_instance_get(service_id_t service_id, ext2fs_instance_t **inst) 185 { 186 EXT2FS_DBG("(%" PRIun ", -)", service_id); 190 187 ext2fs_instance_t *tmp; 191 188 … … 198 195 } 199 196 200 for (link = instance_list.next; link != &instance_list; link = link->next) {197 list_foreach(instance_list, link) { 201 198 tmp = list_get_instance(link, ext2fs_instance_t, link); 202 199 203 if (tmp-> devmap_handle == devmap_handle) {200 if (tmp->service_id == service_id) { 204 201 *inst = tmp; 205 202 fibril_mutex_unlock(&instance_list_mutex); … … 216 213 217 214 218 int ext2fs_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)219 { 220 EXT2FS_DBG("(-, %" PRIun ")", devmap_handle);221 return ext2fs_node_get(rfn, devmap_handle, EXT2_INODE_ROOT_INDEX);215 int ext2fs_root_get(fs_node_t **rfn, service_id_t service_id) 216 { 217 EXT2FS_DBG("(-, %" PRIun ")", service_id); 218 return ext2fs_node_get(rfn, service_id, EXT2_INODE_ROOT_INDEX); 222 219 } 223 220 … … 241 238 } 242 239 243 rc = ext2_directory_iterator_init(&it, fs, eparent->inode_ref );240 rc = ext2_directory_iterator_init(&it, fs, eparent->inode_ref, 0); 244 241 if (rc != EOK) { 245 242 return rc; … … 292 289 293 290 /** Instantiate a EXT2 in-core node. */ 294 int ext2fs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)295 { 296 EXT2FS_DBG("(-,%" PRIun ",%u)", devmap_handle, index);291 int ext2fs_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index) 292 { 293 EXT2FS_DBG("(-,%" PRIun ",%u)", service_id, index); 297 294 298 295 ext2fs_instance_t *inst = NULL; 299 296 int rc; 300 297 301 rc = ext2fs_instance_get( devmap_handle, &inst);298 rc = ext2fs_instance_get(service_id, &inst); 302 299 if (rc != EOK) { 303 300 return rc; … … 320 317 /* Check if the node is not already open */ 321 318 unsigned long key[] = { 322 [OPEN_NODES_DEV_HANDLE_KEY] = inst-> devmap_handle,319 [OPEN_NODES_DEV_HANDLE_KEY] = inst->service_id, 323 320 [OPEN_NODES_INODE_KEY] = index, 324 321 }; … … 414 411 415 412 unsigned long key[] = { 416 [OPEN_NODES_DEV_HANDLE_KEY] = enode->instance-> devmap_handle,413 [OPEN_NODES_DEV_HANDLE_KEY] = enode->instance->service_id, 417 414 [OPEN_NODES_INODE_KEY] = enode->inode_ref->index, 418 415 }; … … 432 429 } 433 430 434 int ext2fs_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int flags)431 int ext2fs_create_node(fs_node_t **rfn, service_id_t service_id, int flags) 435 432 { 436 433 EXT2FS_DBG(""); … … 479 476 } 480 477 481 rc = ext2_directory_iterator_init(&it, fs, enode->inode_ref );478 rc = ext2_directory_iterator_init(&it, fs, enode->inode_ref, 0); 482 479 if (rc != EOK) { 483 480 EXT2FS_DBG("error %u", rc); … … 541 538 } 542 539 543 char ext2fs_plb_get_char(unsigned pos)544 {545 return ext2fs_reg.plb_ro[pos % PLB_SIZE];546 }547 548 540 bool ext2fs_is_directory(fs_node_t *fn) 549 541 { … … 565 557 } 566 558 567 devmap_handle_t ext2fs_device_get(fs_node_t *fn)559 service_id_t ext2fs_device_get(fs_node_t *fn) 568 560 { 569 561 EXT2FS_DBG(""); 570 562 ext2fs_node_t *enode = EXT2FS_NODE(fn); 571 return enode->instance-> devmap_handle;563 return enode->instance->service_id; 572 564 } 573 565 … … 587 579 .size_get = ext2fs_size_get, 588 580 .lnkcnt_get = ext2fs_lnkcnt_get, 589 .plb_get_char = ext2fs_plb_get_char,590 581 .is_directory = ext2fs_is_directory, 591 582 .is_file = ext2fs_is_file, … … 597 588 */ 598 589 599 void ext2fs_mounted(ipc_callid_t rid, ipc_call_t *request) 600 { 601 EXT2FS_DBG(""); 602 int rc;603 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);590 static int ext2fs_mounted(service_id_t service_id, const char *opts, 591 fs_index_t *index, aoff64_t *size, unsigned *lnkcnt) 592 { 593 EXT2FS_DBG(""); 594 int rc; 604 595 ext2_filesystem_t *fs; 605 596 ext2fs_instance_t *inst; 606 597 bool read_only; 607 598 608 /* Accept the mount options */609 char *opts;610 rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);611 612 if (rc != EOK) {613 async_answer_0(rid, rc);614 return;615 }616 617 free(opts);618 619 599 /* Allocate libext2 filesystem structure */ 620 600 fs = (ext2_filesystem_t *) malloc(sizeof(ext2_filesystem_t)); 621 if (fs == NULL) { 622 async_answer_0(rid, ENOMEM); 623 return; 624 } 601 if (fs == NULL) 602 return ENOMEM; 625 603 626 604 /* Allocate instance structure */ … … 628 606 if (inst == NULL) { 629 607 free(fs); 630 async_answer_0(rid, ENOMEM); 631 return; 608 return ENOMEM; 632 609 } 633 610 634 611 /* Initialize the filesystem */ 635 rc = ext2_filesystem_init(fs, devmap_handle);612 rc = ext2_filesystem_init(fs, service_id); 636 613 if (rc != EOK) { 637 614 free(fs); 638 615 free(inst); 639 async_answer_0(rid, rc); 640 return; 616 return rc; 641 617 } 642 618 … … 647 623 free(fs); 648 624 free(inst); 649 async_answer_0(rid, rc); 650 return; 625 return rc; 651 626 } 652 627 … … 657 632 free(fs); 658 633 free(inst); 659 async_answer_0(rid, rc); 660 return; 634 return rc; 661 635 } 662 636 663 637 /* Initialize instance */ 664 638 link_initialize(&inst->link); 665 inst-> devmap_handle = devmap_handle;639 inst->service_id = service_id; 666 640 inst->filesystem = fs; 667 641 inst->open_nodes_count = 0; … … 674 648 free(fs); 675 649 free(inst); 676 async_answer_0(rid, rc); 677 return; 650 return rc; 678 651 } 679 652 ext2fs_node_t *enode = EXT2FS_NODE(root_node); … … 684 657 fibril_mutex_unlock(&instance_list_mutex); 685 658 686 async_answer_3(rid, EOK, 687 EXT2_INODE_ROOT_INDEX, 688 0, 689 ext2_inode_get_usage_count(enode->inode_ref->inode)); 659 *index = EXT2_INODE_ROOT_INDEX; 660 *size = 0; 661 *lnkcnt = ext2_inode_get_usage_count(enode->inode_ref->inode); 690 662 691 663 ext2fs_node_put(root_node); 692 } 693 694 void ext2fs_mount(ipc_callid_t rid, ipc_call_t *request) 695 { 696 EXT2FS_DBG(""); 697 libfs_mount(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request); 698 } 699 700 void ext2fs_unmounted(ipc_callid_t rid, ipc_call_t *request) 701 { 702 EXT2FS_DBG(""); 703 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 664 665 return EOK; 666 } 667 668 static int ext2fs_unmounted(service_id_t service_id) 669 { 670 EXT2FS_DBG(""); 704 671 ext2fs_instance_t *inst; 705 672 int rc; 706 673 707 rc = ext2fs_instance_get(devmap_handle, &inst); 708 709 if (rc != EOK) { 710 async_answer_0(rid, rc); 711 return; 712 } 674 rc = ext2fs_instance_get(service_id, &inst); 675 676 if (rc != EOK) 677 return rc; 713 678 714 679 fibril_mutex_lock(&open_nodes_lock); … … 717 682 if (inst->open_nodes_count != 0) { 718 683 fibril_mutex_unlock(&open_nodes_lock); 719 async_answer_0(rid, EBUSY); 720 return; 684 return EBUSY; 721 685 } 722 686 … … 730 694 ext2_filesystem_fini(inst->filesystem); 731 695 732 async_answer_0(rid, EOK); 733 } 734 735 void ext2fs_unmount(ipc_callid_t rid, ipc_call_t *request) 736 { 737 EXT2FS_DBG(""); 738 libfs_unmount(&ext2fs_libfs_ops, rid, request); 739 } 740 741 void ext2fs_lookup(ipc_callid_t rid, ipc_call_t *request) 742 { 743 EXT2FS_DBG(""); 744 libfs_lookup(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request); 745 } 746 747 void ext2fs_read(ipc_callid_t rid, ipc_call_t *request) 748 { 749 EXT2FS_DBG(""); 750 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 751 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 752 aoff64_t pos = 753 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request)); 696 return EOK; 697 } 698 699 static int 700 ext2fs_read(service_id_t service_id, fs_index_t index, aoff64_t pos, 701 size_t *rbytes) 702 { 703 EXT2FS_DBG(""); 754 704 755 705 ext2fs_instance_t *inst; … … 764 714 if (!async_data_read_receive(&callid, &size)) { 765 715 async_answer_0(callid, EINVAL); 766 async_answer_0(rid, EINVAL); 767 return; 768 } 769 770 rc = ext2fs_instance_get(devmap_handle, &inst); 716 return EINVAL; 717 } 718 719 rc = ext2fs_instance_get(service_id, &inst); 771 720 if (rc != EOK) { 772 721 async_answer_0(callid, rc); 773 async_answer_0(rid, rc); 774 return; 722 return rc; 775 723 } 776 724 … … 778 726 if (rc != EOK) { 779 727 async_answer_0(callid, rc); 780 async_answer_0(rid, rc); 781 return; 728 return rc; 782 729 } 783 730 784 731 if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode, 785 786 ext2fs_read_file(rid, callid, pos, size, inst, inode_ref);787 }788 else if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,789 790 ext2fs_read_directory(rid, callid, pos, size, inst, inode_ref);791 }792 else {732 EXT2_INODE_MODE_FILE)) { 733 rc = ext2fs_read_file(callid, pos, size, inst, inode_ref, 734 rbytes); 735 } else if (ext2_inode_is_type(inst->filesystem->superblock, 736 inode_ref->inode, EXT2_INODE_MODE_DIRECTORY)) { 737 rc = ext2fs_read_directory(callid, pos, size, inst, inode_ref, 738 rbytes); 739 } else { 793 740 /* Other inode types not supported */ 794 741 async_answer_0(callid, ENOTSUP); 795 async_answer_0(rid, ENOTSUP);742 rc = ENOTSUP; 796 743 } 797 744 798 745 ext2_filesystem_put_inode_ref(inode_ref); 799 746 747 return rc; 800 748 } 801 749 … … 815 763 } 816 764 817 void ext2fs_read_directory(ipc_callid_t rid, ipc_callid_t callid, aoff64_t pos,818 size_t size, ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref)765 int ext2fs_read_directory(ipc_callid_t callid, aoff64_t pos, size_t size, 766 ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref, size_t *rbytes) 819 767 { 820 768 ext2_directory_iterator_t it; 821 aoff64_t cur;769 aoff64_t next; 822 770 uint8_t *buf; 823 771 size_t name_size; … … 825 773 bool found = false; 826 774 827 rc = ext2_directory_iterator_init(&it, inst->filesystem, inode_ref );775 rc = ext2_directory_iterator_init(&it, inst->filesystem, inode_ref, pos); 828 776 if (rc != EOK) { 829 777 async_answer_0(callid, rc); 830 async_answer_0(rid, rc); 831 return; 832 } 833 834 /* Find the index we want to read 835 * Note that we need to iterate and count as 836 * the underlying structure is a linked list 837 * Moreover, we want to skip . and .. entries 778 return rc; 779 } 780 781 /* Find next interesting directory entry. 782 * We want to skip . and .. entries 838 783 * as these are not used in HelenOS 839 784 */ 840 cur = 0;841 785 while (it.current != NULL) { 842 786 if (it.current->inode == 0) { … … 845 789 846 790 name_size = ext2_directory_entry_ll_get_name_length( 847 791 inst->filesystem->superblock, it.current); 848 792 849 793 /* skip . and .. */ … … 852 796 } 853 797 854 /* Is this the dir entry we want to read? */ 855 if (cur == pos) { 856 /* The on-disk entry does not contain \0 at the end 857 * end of entry name, so we copy it to new buffer 858 * and add the \0 at the end 859 */ 860 buf = malloc(name_size+1); 861 if (buf == NULL) { 862 ext2_directory_iterator_fini(&it); 863 async_answer_0(callid, ENOMEM); 864 async_answer_0(rid, ENOMEM); 865 return; 866 } 867 memcpy(buf, &it.current->name, name_size); 868 *(buf+name_size) = 0; 869 found = true; 870 (void) async_data_read_finalize(callid, buf, name_size+1); 871 free(buf); 872 break; 873 } 874 cur++; 798 /* The on-disk entry does not contain \0 at the end 799 * end of entry name, so we copy it to new buffer 800 * and add the \0 at the end 801 */ 802 buf = malloc(name_size+1); 803 if (buf == NULL) { 804 ext2_directory_iterator_fini(&it); 805 async_answer_0(callid, ENOMEM); 806 return ENOMEM; 807 } 808 memcpy(buf, &it.current->name, name_size); 809 *(buf + name_size) = 0; 810 found = true; 811 (void) async_data_read_finalize(callid, buf, name_size + 1); 812 free(buf); 813 break; 875 814 876 815 skip: … … 879 818 ext2_directory_iterator_fini(&it); 880 819 async_answer_0(callid, rc); 881 async_answer_0(rid, rc); 882 return; 883 } 820 return rc; 821 } 822 } 823 824 if (found) { 825 rc = ext2_directory_iterator_next(&it); 826 if (rc != EOK) 827 return rc; 828 next = it.current_offset; 884 829 } 885 830 886 831 rc = ext2_directory_iterator_fini(&it); 887 if (rc != EOK) { 888 async_answer_0(rid, rc); 889 return; 890 } 832 if (rc != EOK) 833 return rc; 891 834 892 835 if (found) { 893 async_answer_1(rid, EOK, 1);894 }895 else {836 *rbytes = next - pos; 837 return EOK; 838 } else { 896 839 async_answer_0(callid, ENOENT); 897 async_answer_0(rid, ENOENT);898 } 899 } 900 901 void ext2fs_read_file(ipc_callid_t rid, ipc_callid_t callid, aoff64_t pos,902 size_t size, ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref)840 return ENOENT; 841 } 842 } 843 844 int ext2fs_read_file(ipc_callid_t callid, aoff64_t pos, size_t size, 845 ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref, size_t *rbytes) 903 846 { 904 847 int rc; … … 918 861 /* Read 0 bytes successfully */ 919 862 async_data_read_finalize(callid, NULL, 0); 920 async_answer_1(rid, EOK, 0);921 return ;863 *rbytes = 0; 864 return EOK; 922 865 } 923 866 … … 938 881 if (rc != EOK) { 939 882 async_answer_0(callid, rc); 940 async_answer_0(rid, rc); 941 return; 883 return rc; 942 884 } 943 885 … … 951 893 if (buffer == NULL) { 952 894 async_answer_0(callid, ENOMEM); 953 async_answer_0(rid, ENOMEM); 954 return; 895 return ENOMEM; 955 896 } 956 897 … … 958 899 959 900 async_data_read_finalize(callid, buffer, bytes); 960 async_answer_1(rid, EOK, bytes);901 *rbytes = bytes; 961 902 962 903 free(buffer); 963 904 964 return ;905 return EOK; 965 906 } 966 907 967 908 /* Usual case - we need to read a block from device */ 968 rc = block_get(&block, inst-> devmap_handle, fs_block, BLOCK_FLAGS_NONE);909 rc = block_get(&block, inst->service_id, fs_block, BLOCK_FLAGS_NONE); 969 910 if (rc != EOK) { 970 911 async_answer_0(callid, rc); 971 async_answer_0(rid, rc); 972 return; 912 return rc; 973 913 } 974 914 … … 977 917 978 918 rc = block_put(block); 979 if (rc != EOK) { 980 async_answer_0(rid, rc); 981 return; 982 } 983 984 async_answer_1(rid, EOK, bytes); 985 } 986 987 void ext2fs_write(ipc_callid_t rid, ipc_call_t *request) 988 { 989 EXT2FS_DBG(""); 990 // devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 991 // fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 992 // aoff64_t pos = 993 // (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request)); 994 995 // TODO 996 async_answer_0(rid, ENOTSUP); 997 } 998 999 void ext2fs_truncate(ipc_callid_t rid, ipc_call_t *request) 1000 { 1001 EXT2FS_DBG(""); 1002 // devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 1003 // fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 1004 // aoff64_t size = 1005 // (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request)); 1006 1007 // TODO 1008 async_answer_0(rid, ENOTSUP); 1009 } 1010 1011 void ext2fs_close(ipc_callid_t rid, ipc_call_t *request) 1012 { 1013 EXT2FS_DBG(""); 1014 async_answer_0(rid, EOK); 1015 } 1016 1017 void ext2fs_destroy(ipc_callid_t rid, ipc_call_t *request) 1018 { 1019 EXT2FS_DBG(""); 1020 // devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request); 1021 // fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1022 1023 // TODO 1024 async_answer_0(rid, ENOTSUP); 1025 } 1026 1027 void ext2fs_open_node(ipc_callid_t rid, ipc_call_t *request) 1028 { 1029 EXT2FS_DBG(""); 1030 libfs_open_node(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request); 1031 } 1032 1033 void ext2fs_stat(ipc_callid_t rid, ipc_call_t *request) 1034 { 1035 EXT2FS_DBG(""); 1036 libfs_stat(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request); 1037 } 1038 1039 void ext2fs_sync(ipc_callid_t rid, ipc_call_t *request) 1040 { 1041 EXT2FS_DBG(""); 1042 // devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 1043 // fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 1044 1045 // TODO 1046 async_answer_0(rid, ENOTSUP); 1047 } 919 if (rc != EOK) 920 return rc; 921 922 *rbytes = bytes; 923 return EOK; 924 } 925 926 static int 927 ext2fs_write(service_id_t service_id, fs_index_t index, aoff64_t pos, 928 size_t *wbytes, aoff64_t *nsize) 929 { 930 EXT2FS_DBG(""); 931 return ENOTSUP; 932 } 933 934 static int 935 ext2fs_truncate(service_id_t service_id, fs_index_t index, aoff64_t size) 936 { 937 EXT2FS_DBG(""); 938 return ENOTSUP; 939 } 940 941 static int ext2fs_close(service_id_t service_id, fs_index_t index) 942 { 943 EXT2FS_DBG(""); 944 return EOK; 945 } 946 947 static int ext2fs_destroy(service_id_t service_id, fs_index_t index) 948 { 949 EXT2FS_DBG(""); 950 return ENOTSUP; 951 } 952 953 static int ext2fs_sync(service_id_t service_id, fs_index_t index) 954 { 955 EXT2FS_DBG(""); 956 return ENOTSUP; 957 } 958 959 vfs_out_ops_t ext2fs_ops = { 960 .mounted = ext2fs_mounted, 961 .unmounted = ext2fs_unmounted, 962 .read = ext2fs_read, 963 .write = ext2fs_write, 964 .truncate = ext2fs_truncate, 965 .close = ext2fs_close, 966 .destroy = ext2fs_destroy, 967 .sync = ext2fs_sync, 968 }; 1048 969 1049 970 /** 1050 971 * @} 1051 972 */ 973 -
uspace/srv/fs/fat/Makefile
rd2c67e7 r8ff0bd2 39 39 fat_idx.c \ 40 40 fat_dentry.c \ 41 fat_directory.c \ 41 42 fat_fat.c 42 43 -
uspace/srv/fs/fat/fat.c
rd2c67e7 r8ff0bd2 2 2 * Copyright (c) 2006 Martin Decky 3 3 * Copyright (c) 2008 Jakub Jermar 4 * Copyright (c) 2011 Oleg Romanenko 4 5 * All rights reserved. 5 6 * … … 56 57 }; 57 58 58 fs_reg_t fat_reg;59 60 /**61 * This connection fibril processes VFS requests from VFS.62 *63 * In order to support simultaneous VFS requests, our design is as follows.64 * The connection fibril accepts VFS requests from VFS. If there is only one65 * instance of the fibril, VFS will need to serialize all VFS requests it sends66 * to FAT. To overcome this bottleneck, VFS can send FAT the IPC_M_CONNECT_ME_TO67 * call. In that case, a new connection fibril will be created, which in turn68 * will accept the call. Thus, a new phone will be opened for VFS.69 *70 * There are few issues with this arrangement. First, VFS can run out of71 * available phones. In that case, VFS can close some other phones or use one72 * phone for more serialized requests. Similarily, FAT can refuse to duplicate73 * the connection. VFS should then just make use of already existing phones and74 * route its requests through them. To avoid paying the fibril creation price75 * upon each request, FAT might want to keep the connections open after the76 * request has been completed.77 */78 static void fat_connection(ipc_callid_t iid, ipc_call_t *icall)79 {80 if (iid) {81 /*82 * This only happens for connections opened by83 * IPC_M_CONNECT_ME_TO calls as opposed to callback connections84 * created by IPC_M_CONNECT_TO_ME.85 */86 async_answer_0(iid, EOK);87 }88 89 dprintf(NAME ": connection opened\n");90 91 while (true) {92 ipc_call_t call;93 ipc_callid_t callid = async_get_call(&call);94 95 if (!IPC_GET_IMETHOD(call))96 return;97 98 switch (IPC_GET_IMETHOD(call)) {99 case VFS_OUT_MOUNTED:100 fat_mounted(callid, &call);101 break;102 case VFS_OUT_MOUNT:103 fat_mount(callid, &call);104 break;105 case VFS_OUT_UNMOUNTED:106 fat_unmounted(callid, &call);107 break;108 case VFS_OUT_UNMOUNT:109 fat_unmount(callid, &call);110 break;111 case VFS_OUT_LOOKUP:112 fat_lookup(callid, &call);113 break;114 case VFS_OUT_READ:115 fat_read(callid, &call);116 break;117 case VFS_OUT_WRITE:118 fat_write(callid, &call);119 break;120 case VFS_OUT_TRUNCATE:121 fat_truncate(callid, &call);122 break;123 case VFS_OUT_STAT:124 fat_stat(callid, &call);125 break;126 case VFS_OUT_CLOSE:127 fat_close(callid, &call);128 break;129 case VFS_OUT_DESTROY:130 fat_destroy(callid, &call);131 break;132 case VFS_OUT_OPEN_NODE:133 fat_open_node(callid, &call);134 break;135 case VFS_OUT_SYNC:136 fat_sync(callid, &call);137 break;138 default:139 async_answer_0(callid, ENOTSUP);140 break;141 }142 }143 }144 145 59 int main(int argc, char **argv) 146 60 { … … 158 72 } 159 73 160 rc = fs_register(vfs_sess, &fat_ reg, &fat_vfs_info, fat_connection);74 rc = fs_register(vfs_sess, &fat_vfs_info, &fat_ops, &fat_libfs_ops); 161 75 if (rc != EOK) { 162 76 fat_idx_fini(); -
uspace/srv/fs/fat/fat.h
rd2c67e7 r8ff0bd2 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 46 47 #endif 47 48 48 #define min(a, b) 49 #define min(a, b) ((a) < (b) ? (a) : (b)) 49 50 50 51 /* … … 55 56 #define RSCNT(bs) uint16_t_le2host((bs)->rscnt) 56 57 #define FATCNT(bs) (bs)->fatcnt 57 #define SF(bs) uint16_t_le2host((bs)->sec_per_fat) 58 59 #define SF(bs) (uint16_t_le2host((bs)->sec_per_fat) ? \ 60 uint16_t_le2host((bs)->sec_per_fat) : \ 61 uint32_t_le2host(bs->fat32.sectors_per_fat)) 62 58 63 #define RDE(bs) uint16_t_le2host((bs)->root_ent_max) 59 #define TS(bs) (uint16_t_le2host((bs)->totsec16) != 0 ? \ 60 uint16_t_le2host((bs)->totsec16) : \ 61 uint32_t_le2host(bs->totsec32)) 62 63 #define BS_BLOCK 0 64 #define BS_SIZE 512 64 65 #define TS(bs) (uint16_t_le2host((bs)->totsec16) ? \ 66 uint16_t_le2host((bs)->totsec16) : \ 67 uint32_t_le2host(bs->totsec32)) 68 69 #define BS_BLOCK 0 70 #define BS_SIZE 512 65 71 66 72 typedef struct fat_bs { … … 175 181 176 182 fibril_mutex_t lock; 177 devmap_handle_t devmap_handle;183 service_id_t service_id; 178 184 fs_index_t index; 179 185 /** … … 224 230 } fat_node_t; 225 231 226 extern fs_reg_t fat_reg; 227 228 extern void fat_mounted(ipc_callid_t, ipc_call_t *); 229 extern void fat_mount(ipc_callid_t, ipc_call_t *); 230 extern void fat_unmounted(ipc_callid_t, ipc_call_t *); 231 extern void fat_unmount(ipc_callid_t, ipc_call_t *); 232 extern void fat_lookup(ipc_callid_t, ipc_call_t *); 233 extern void fat_read(ipc_callid_t, ipc_call_t *); 234 extern void fat_write(ipc_callid_t, ipc_call_t *); 235 extern void fat_truncate(ipc_callid_t, ipc_call_t *); 236 extern void fat_stat(ipc_callid_t, ipc_call_t *); 237 extern void fat_close(ipc_callid_t, ipc_call_t *); 238 extern void fat_destroy(ipc_callid_t, ipc_call_t *); 239 extern void fat_open_node(ipc_callid_t, ipc_call_t *); 240 extern void fat_stat(ipc_callid_t, ipc_call_t *); 241 extern void fat_sync(ipc_callid_t, ipc_call_t *); 242 243 extern int fat_idx_get_new(fat_idx_t **, devmap_handle_t); 244 extern fat_idx_t *fat_idx_get_by_pos(devmap_handle_t, fat_cluster_t, unsigned); 245 extern fat_idx_t *fat_idx_get_by_index(devmap_handle_t, fs_index_t); 232 extern vfs_out_ops_t fat_ops; 233 extern libfs_ops_t fat_libfs_ops; 234 235 extern int fat_idx_get_new(fat_idx_t **, service_id_t); 236 extern fat_idx_t *fat_idx_get_by_pos(service_id_t, fat_cluster_t, unsigned); 237 extern fat_idx_t *fat_idx_get_by_index(service_id_t, fs_index_t); 246 238 extern void fat_idx_destroy(fat_idx_t *); 247 239 extern void fat_idx_hashin(fat_idx_t *); … … 250 242 extern int fat_idx_init(void); 251 243 extern void fat_idx_fini(void); 252 extern int fat_idx_init_by_ devmap_handle(devmap_handle_t);253 extern void fat_idx_fini_by_ devmap_handle(devmap_handle_t);244 extern int fat_idx_init_by_service_id(service_id_t); 245 extern void fat_idx_fini_by_service_id(service_id_t); 254 246 255 247 #endif -
uspace/srv/fs/fat/fat_dentry.c
rd2c67e7 r8ff0bd2 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 39 40 #include <ctype.h> 40 41 #include <str.h> 41 42 static bool is_d_char(const char ch) 43 { 44 if (isalnum(ch) || ch == '_') 45 return true; 46 else 47 return false; 48 } 42 #include <errno.h> 43 #include <byteorder.h> 44 #include <assert.h> 49 45 50 46 /** Compare path component with the name read from the dentry. … … 80 76 } 81 77 82 bool fat_dentry_name_verify(const char *name) 78 void fat_dentry_name_get(const fat_dentry_t *d, char *buf) 79 { 80 unsigned int i; 81 82 for (i = 0; i < FAT_NAME_LEN; i++) { 83 if (d->name[i] == FAT_PAD) 84 break; 85 86 if (d->name[i] == FAT_DENTRY_E5_ESC) 87 *buf++ = 0xe5; 88 else { 89 if (d->lcase & FAT_LCASE_LOWER_NAME) 90 *buf++ = tolower(d->name[i]); 91 else 92 *buf++ = d->name[i]; 93 } 94 } 95 96 if (d->ext[0] != FAT_PAD) 97 *buf++ = '.'; 98 99 for (i = 0; i < FAT_EXT_LEN; i++) { 100 if (d->ext[i] == FAT_PAD) { 101 *buf = '\0'; 102 return; 103 } 104 105 if (d->ext[i] == FAT_DENTRY_E5_ESC) 106 *buf++ = 0xe5; 107 else { 108 if (d->lcase & FAT_LCASE_LOWER_EXT) 109 *buf++ = tolower(d->ext[i]); 110 else 111 *buf++ = d->ext[i]; 112 } 113 } 114 115 *buf = '\0'; 116 } 117 118 void fat_dentry_name_set(fat_dentry_t *d, const char *name) 119 { 120 unsigned int i; 121 const char fake_ext[] = " "; 122 bool lower_name = true; 123 bool lower_ext = true; 124 125 for (i = 0; i < FAT_NAME_LEN; i++) { 126 switch ((uint8_t) *name) { 127 case 0xe5: 128 d->name[i] = FAT_DENTRY_E5_ESC; 129 name++; 130 break; 131 case '\0': 132 case '.': 133 d->name[i] = FAT_PAD; 134 break; 135 default: 136 if (isalpha(*name)) { 137 if (!islower(*name)) 138 lower_name = false; 139 } 140 141 d->name[i] = toupper(*name++); 142 break; 143 } 144 } 145 146 if (*name++ != '.') 147 name = fake_ext; 148 149 for (i = 0; i < FAT_EXT_LEN; i++) { 150 switch ((uint8_t) *name) { 151 case 0xe5: 152 d->ext[i] = FAT_DENTRY_E5_ESC; 153 name++; 154 break; 155 case '\0': 156 d->ext[i] = FAT_PAD; 157 break; 158 default: 159 if (isalpha(*name)) { 160 if (!islower(*name)) 161 lower_ext = false; 162 } 163 164 d->ext[i] = toupper(*name++); 165 break; 166 } 167 } 168 169 if (lower_name) 170 d->lcase |= FAT_LCASE_LOWER_NAME; 171 else 172 d->lcase &= ~FAT_LCASE_LOWER_NAME; 173 174 if (lower_ext) 175 d->lcase |= FAT_LCASE_LOWER_EXT; 176 else 177 d->lcase &= ~FAT_LCASE_LOWER_EXT; 178 } 179 180 fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d) 181 { 182 if (d->attr == FAT_ATTR_LFN) { 183 /* long name entry */ 184 if (FAT_LFN_ORDER(d) & FAT_LFN_ERASED) 185 return FAT_DENTRY_FREE; 186 else 187 return FAT_DENTRY_LFN; 188 } 189 if (d->attr & FAT_ATTR_VOLLABEL) { 190 /* volume label entry */ 191 return FAT_DENTRY_SKIP; 192 } 193 if (d->name[0] == FAT_DENTRY_ERASED) { 194 /* not-currently-used entry */ 195 return FAT_DENTRY_FREE; 196 } 197 if (d->name[0] == FAT_DENTRY_UNUSED) { 198 /* never used entry */ 199 return FAT_DENTRY_LAST; 200 } 201 if (d->name[0] == FAT_DENTRY_DOT) { 202 /* 203 * Most likely '.' or '..'. 204 * It cannot occur in a regular file name. 205 */ 206 return FAT_DENTRY_SKIP; 207 } 208 return FAT_DENTRY_VALID; 209 } 210 211 /** Compute checksum of Node name. 212 * 213 * Returns an unsigned byte checksum computed on an unsigned byte 214 * array. The array must be 11 bytes long and is assumed to contain 215 * a name stored in the format of a MS-DOS directory entry. 216 * 217 * @param name Node name read from the dentry. 218 * 219 * @return An 8-bit unsigned checksum of the name. 220 */ 221 uint8_t fat_dentry_chksum(uint8_t *name) 222 { 223 uint8_t i, sum = 0; 224 225 for (i = 0; i < (FAT_NAME_LEN + FAT_EXT_LEN); i++) 226 sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + name[i]; 227 228 return sum; 229 } 230 231 /** Get number of bytes in a string with size limit. 232 * 233 * @param str NULL-terminated (or not) string. 234 * @param size Maximum number of bytes to consider. 235 * 236 * @return Number of bytes in string (without 0 and ff). 237 * 238 */ 239 size_t fat_lfn_str_nlength(const uint16_t *str, size_t size) 240 { 241 size_t offset = 0; 242 243 while (offset < size) { 244 if (str[offset] == 0 || str[offset] == FAT_LFN_PAD) 245 break; 246 offset++; 247 } 248 return offset; 249 } 250 251 /** Get number of bytes in a FAT long entry occuped by characters. 252 * 253 * @param d FAT long entry. 254 * 255 * @return Number of bytes. 256 * 257 */ 258 size_t fat_lfn_size(const fat_dentry_t *d) 259 { 260 size_t size = 0; 261 262 size += fat_lfn_str_nlength(FAT_LFN_PART1(d), FAT_LFN_PART1_SIZE); 263 size += fat_lfn_str_nlength(FAT_LFN_PART2(d), FAT_LFN_PART2_SIZE); 264 size += fat_lfn_str_nlength(FAT_LFN_PART3(d), FAT_LFN_PART3_SIZE); 265 266 return size; 267 } 268 269 size_t fat_lfn_get_entry(const fat_dentry_t *d, uint16_t *dst, size_t *offset) 270 { 271 int i; 272 for (i = FAT_LFN_PART3_SIZE - 1; i >= 0 && *offset > 0; i--) { 273 if (d->lfn.part3[i] == 0 || d->lfn.part3[i] == FAT_LFN_PAD) 274 continue; 275 (*offset)--; 276 dst[(*offset)] = uint16_t_le2host(d->lfn.part3[i]); 277 } 278 for (i = FAT_LFN_PART2_SIZE - 1; i >= 0 && *offset > 0; i--) { 279 if (d->lfn.part2[i] == 0 || d->lfn.part2[i] == FAT_LFN_PAD) 280 continue; 281 (*offset)--; 282 dst[(*offset)] = uint16_t_le2host(d->lfn.part2[i]); 283 } 284 for (i = FAT_LFN_PART1_SIZE - 1; i >= 0 && *offset > 0; i--) { 285 if (d->lfn.part1[i] == 0 || d->lfn.part1[i] == FAT_LFN_PAD) 286 continue; 287 (*offset)--; 288 dst[(*offset)] = uint16_t_le2host(d->lfn.part1[i]); 289 } 290 return *offset; 291 } 292 293 size_t fat_lfn_set_entry(const uint16_t *src, size_t *offset, size_t size, 294 fat_dentry_t *d) 295 { 296 size_t idx; 297 for (idx = 0; idx < FAT_LFN_PART1_SIZE; idx++) { 298 if (*offset < size) { 299 d->lfn.part1[idx] = host2uint16_t_le(src[*offset]); 300 (*offset)++; 301 } else 302 d->lfn.part1[idx] = FAT_LFN_PAD; 303 } 304 for (idx = 0; idx < FAT_LFN_PART2_SIZE; idx++) { 305 if (*offset < size) { 306 d->lfn.part2[idx] = host2uint16_t_le(src[*offset]); 307 (*offset)++; 308 } else 309 d->lfn.part2[idx] = FAT_LFN_PAD; 310 } 311 for (idx = 0; idx < FAT_LFN_PART3_SIZE; idx++) { 312 if (*offset < size) { 313 d->lfn.part3[idx] = host2uint16_t_le(src[*offset]); 314 (*offset)++; 315 } else 316 d->lfn.part3[idx] = FAT_LFN_PAD; 317 } 318 319 if (src[*offset] == 0) 320 offset++; 321 FAT_LFN_ATTR(d) = FAT_ATTR_LFN; 322 d->lfn.type = 0; 323 d->lfn.firstc_lo = 0; 324 325 return *offset; 326 } 327 328 void str_to_ascii(char *dst, const char *src, size_t count, uint8_t pad) 329 { 330 wchar_t ch; 331 size_t off = 0; 332 size_t i = 0; 333 334 while (i < count) { 335 if ((ch = str_decode(src, &off, STR_NO_LIMIT)) != 0) { 336 if (ascii_check(ch) & IS_D_CHAR(ch)) 337 *dst = toupper(ch); 338 else 339 *dst = pad; 340 } else 341 break; 342 343 dst++; 344 i++; 345 } 346 *dst = '\0'; 347 } 348 349 bool fat_valid_name(const char *name) 350 { 351 wchar_t ch; 352 size_t offset=0; 353 bool result = true; 354 355 while ((ch = str_decode(name, &offset, STR_NO_LIMIT)) != 0) { 356 if (str_chr(FAT_STOP_CHARS, ch) != NULL) { 357 result = false; 358 break; 359 } 360 } 361 return result; 362 } 363 364 bool fat_valid_short_name(const char *name) 83 365 { 84 366 unsigned int i; 85 367 unsigned int dot = 0; 86 368 bool dot_found = false; 87 88 369 89 370 for (i = 0; name[i]; i++) { … … 96 377 } 97 378 } else { 98 if (! is_d_char(name[i]))379 if (!IS_D_CHAR(name[i])) 99 380 return false; 100 381 } … … 114 395 } 115 396 116 void fat_dentry_name_get(const fat_dentry_t *d, char *buf) 117 { 118 unsigned int i; 119 120 for (i = 0; i < FAT_NAME_LEN; i++) { 121 if (d->name[i] == FAT_PAD) 122 break; 123 124 if (d->name[i] == FAT_DENTRY_E5_ESC) 125 *buf++ = 0xe5; 126 else { 127 if (d->lcase & FAT_LCASE_LOWER_NAME) 128 *buf++ = tolower(d->name[i]); 129 else 130 *buf++ = d->name[i]; 131 } 132 } 133 134 if (d->ext[0] != FAT_PAD) 135 *buf++ = '.'; 136 137 for (i = 0; i < FAT_EXT_LEN; i++) { 138 if (d->ext[i] == FAT_PAD) { 139 *buf = '\0'; 140 return; 141 } 142 143 if (d->ext[i] == FAT_DENTRY_E5_ESC) 144 *buf++ = 0xe5; 145 else { 146 if (d->lcase & FAT_LCASE_LOWER_EXT) 147 *buf++ = tolower(d->ext[i]); 148 else 149 *buf++ = d->ext[i]; 150 } 151 } 152 153 *buf = '\0'; 154 } 155 156 void fat_dentry_name_set(fat_dentry_t *d, const char *name) 157 { 158 unsigned int i; 159 const char fake_ext[] = " "; 160 bool lower_name = true; 161 bool lower_ext = true; 162 163 for (i = 0; i < FAT_NAME_LEN; i++) { 164 switch ((uint8_t) *name) { 165 case 0xe5: 166 d->name[i] = FAT_DENTRY_E5_ESC; 167 name++; 168 break; 169 case '\0': 170 case '.': 171 d->name[i] = FAT_PAD; 172 break; 173 default: 174 if (isalpha(*name)) { 175 if (!islower(*name)) 176 lower_name = false; 177 } 178 179 d->name[i] = toupper(*name++); 180 break; 181 } 182 } 183 184 if (*name++ != '.') 185 name = fake_ext; 186 187 for (i = 0; i < FAT_EXT_LEN; i++) { 188 switch ((uint8_t) *name) { 189 case 0xe5: 190 d->ext[i] = FAT_DENTRY_E5_ESC; 191 name++; 192 break; 193 case '\0': 194 d->ext[i] = FAT_PAD; 195 break; 196 default: 197 if (isalpha(*name)) { 198 if (!islower(*name)) 199 lower_ext = false; 200 } 201 202 d->ext[i] = toupper(*name++); 203 break; 204 } 205 } 206 207 if (lower_name) 208 d->lcase |= FAT_LCASE_LOWER_NAME; 209 else 210 d->lcase &= ~FAT_LCASE_LOWER_NAME; 211 212 if (lower_ext) 213 d->lcase |= FAT_LCASE_LOWER_EXT; 214 else 215 d->lcase &= ~FAT_LCASE_LOWER_EXT; 216 } 217 218 fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d) 219 { 220 if (d->attr & FAT_ATTR_VOLLABEL) { 221 /* volume label entry */ 222 return FAT_DENTRY_SKIP; 223 } 224 if (d->name[0] == FAT_DENTRY_ERASED) { 225 /* not-currently-used entry */ 226 return FAT_DENTRY_FREE; 227 } 228 if (d->name[0] == FAT_DENTRY_UNUSED) { 229 /* never used entry */ 230 return FAT_DENTRY_LAST; 231 } 232 if (d->name[0] == FAT_DENTRY_DOT) { 233 /* 234 * Most likely '.' or '..'. 235 * It cannot occur in a regular file name. 236 */ 237 return FAT_DENTRY_SKIP; 238 } 239 return FAT_DENTRY_VALID; 397 size_t utf16_length(const uint16_t *wstr) 398 { 399 size_t len = 0; 400 401 while (*wstr++ != 0) 402 len++; 403 404 return len; 240 405 } 241 406 -
uspace/srv/fs/fat/fat_dentry.h
rd2c67e7 r8ff0bd2 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 37 38 #include <bool.h> 38 39 40 #define IS_D_CHAR(ch) (isalnum(ch) || ch == '_') 41 #define FAT_STOP_CHARS "*?/\\\n\t|'" 42 39 43 #define FAT_NAME_LEN 8 40 44 #define FAT_EXT_LEN 3 … … 44 48 #define FAT_EXT_PAD " " 45 49 46 #define FAT_ATTR_RDONLY (1 << 0) 47 #define FAT_ATTR_VOLLABEL (1 << 3) 48 #define FAT_ATTR_SUBDIR (1 << 4) 49 50 #define FAT_ATTR_RDONLY 0x01 51 #define FAT_ATTR_HIDDEN 0x02 52 #define FAT_ATTR_SYSTEM 0x04 53 #define FAT_ATTR_VOLLABEL 0x08 54 #define FAT_ATTR_SUBDIR 0x10 55 #define FAT_ATTR_ARCHIVE 0x20 56 #define FAT_ATTR_LFN \ 57 (FAT_ATTR_RDONLY | FAT_ATTR_HIDDEN | FAT_ATTR_SYSTEM | FAT_ATTR_VOLLABEL) 58 50 59 #define FAT_LCASE_LOWER_NAME 0x08 51 60 #define FAT_LCASE_LOWER_EXT 0x10 52 61 53 #define FAT_PAD ' ' 62 #define FAT_PAD ' ' 63 #define FAT_LFN_PAD 0xffff 64 #define FAT_SFN_CHAR '_' 54 65 55 66 #define FAT_DENTRY_UNUSED 0x00 … … 57 68 #define FAT_DENTRY_DOT 0x2e 58 69 #define FAT_DENTRY_ERASED 0xe5 70 #define FAT_LFN_LAST 0x40 71 #define FAT_LFN_ERASED 0x80 72 73 #define FAT_LFN_ORDER(d) ((d)->lfn.order) 74 #define FAT_IS_LFN(d) \ 75 ((FAT_LFN_ORDER((d)) & FAT_LFN_LAST) == FAT_LFN_LAST) 76 #define FAT_LFN_COUNT(d) \ 77 (FAT_LFN_ORDER((d)) ^ FAT_LFN_LAST) 78 #define FAT_LFN_PART1(d) ((d)->lfn.part1) 79 #define FAT_LFN_PART2(d) ((d)->lfn.part2) 80 #define FAT_LFN_PART3(d) ((d)->lfn.part3) 81 #define FAT_LFN_ATTR(d) ((d)->lfn.attr) 82 #define FAT_LFN_CHKSUM(d) ((d)->lfn.check_sum) 83 84 #define FAT_LFN_NAME_SIZE 260 85 #define FAT_LFN_MAX_COUNT 20 86 #define FAT_LFN_PART1_SIZE 5 87 #define FAT_LFN_PART2_SIZE 6 88 #define FAT_LFN_PART3_SIZE 2 89 #define FAT_LFN_ENTRY_SIZE \ 90 (FAT_LFN_PART1_SIZE + FAT_LFN_PART2_SIZE + FAT_LFN_PART3_SIZE) 59 91 60 92 typedef enum { … … 62 94 FAT_DENTRY_LAST, 63 95 FAT_DENTRY_FREE, 64 FAT_DENTRY_VALID 96 FAT_DENTRY_VALID, 97 FAT_DENTRY_LFN 65 98 } fat_dentry_clsf_t; 66 99 67 typedef struct { 68 uint8_t name[8]; 69 uint8_t ext[3]; 70 uint8_t attr; 71 uint8_t lcase; 72 uint8_t ctime_fine; 73 uint16_t ctime; 74 uint16_t cdate; 75 uint16_t adate; 76 union { 77 uint16_t eaidx; /* FAT12/FAT16 */ 78 uint16_t firstc_hi; /* FAT32 */ 100 typedef union { 101 struct { 102 uint8_t name[8]; 103 uint8_t ext[3]; 104 uint8_t attr; 105 uint8_t lcase; 106 uint8_t ctime_fine; 107 uint16_t ctime; 108 uint16_t cdate; 109 uint16_t adate; 110 union { 111 uint16_t eaidx; /* FAT12/FAT16 */ 112 uint16_t firstc_hi; /* FAT32 */ 113 } __attribute__ ((packed)); 114 uint16_t mtime; 115 uint16_t mdate; 116 union { 117 uint16_t firstc; /* FAT12/FAT16 */ 118 uint16_t firstc_lo; /* FAT32 */ 119 } __attribute__ ((packed)); 120 uint32_t size; 79 121 } __attribute__ ((packed)); 80 uint16_t mtime; 81 uint16_t mdate; 82 union { 83 uint16_t firstc; /* FAT12/FAT16 */ 84 uint16_t firstc_lo; /* FAT32 */ 85 } __attribute__ ((packed)); 86 uint32_t size; 122 struct { 123 uint8_t order; 124 uint16_t part1[FAT_LFN_PART1_SIZE]; 125 uint8_t attr; 126 uint8_t type; 127 uint8_t check_sum; 128 uint16_t part2[FAT_LFN_PART2_SIZE]; 129 uint16_t firstc_lo; /* MUST be 0 */ 130 uint16_t part3[FAT_LFN_PART3_SIZE]; 131 } __attribute__ ((packed)) lfn; 87 132 } __attribute__ ((packed)) fat_dentry_t; 88 133 134 89 135 extern int fat_dentry_namecmp(char *, const char *); 90 extern bool fat_dentry_name_verify(const char *);91 136 extern void fat_dentry_name_get(const fat_dentry_t *, char *); 92 137 extern void fat_dentry_name_set(fat_dentry_t *, const char *); 93 138 extern fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *); 139 extern uint8_t fat_dentry_chksum(uint8_t *); 140 141 extern size_t fat_lfn_str_nlength(const uint16_t *, size_t); 142 extern size_t fat_lfn_size(const fat_dentry_t *); 143 extern size_t fat_lfn_get_entry(const fat_dentry_t *, uint16_t *, size_t *); 144 extern size_t fat_lfn_set_entry(const uint16_t *, size_t *, size_t, 145 fat_dentry_t *); 146 147 extern void str_to_ascii(char *, const char *, size_t, uint8_t); 148 extern size_t utf16_length(const uint16_t *); 149 150 extern bool fat_valid_name(const char *); 151 extern bool fat_valid_short_name(const char *); 94 152 95 153 #endif -
uspace/srv/fs/fat/fat_fat.c
rd2c67e7 r8ff0bd2 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 29 30 /** @addtogroup fs 30 31 * @{ 31 */ 32 */ 32 33 33 34 /** … … 50 51 #include <mem.h> 51 52 52 /* 53 * Convenience macros for computing some frequently used values from the 54 * primitive boot sector members. 55 */ 56 #define RDS(bs) ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \ 57 (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0) 58 #define SSA(bs) (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs)) 59 60 #define CLBN2PBN(bs, cl, bn) \ 61 (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs))) 53 #define IS_ODD(number) (number & 0x1) 62 54 63 55 /** … … 65 57 * during allocation of clusters. The lock does not have to be held durring 66 58 * deallocation of clusters. 67 */ 59 */ 68 60 static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock); 69 61 … … 71 63 * 72 64 * @param bs Buffer holding the boot sector for the file. 73 * @param devmap_handle Device handleof the device with the file.65 * @param service_id Service ID of the device with the file. 74 66 * @param firstc First cluster to start the walk with. 75 67 * @param lastc If non-NULL, output argument hodling the last cluster … … 77 69 * @param numc If non-NULL, output argument holding the number of 78 70 * clusters seen during the walk. 79 * @param max_clusters Maximum number of clusters to visit. 71 * @param max_clusters Maximum number of clusters to visit. 80 72 * 81 73 * @return EOK on success or a negative error code. 82 74 */ 83 int 84 fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc,85 fat_cluster_t *lastc, uint 16_t *numc, uint16_t max_clusters)86 { 87 block_t *b;88 uint16_t clusters = 0;89 fat_cluster_t clst = firstc;75 int 76 fat_cluster_walk(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc, 77 fat_cluster_t *lastc, uint32_t *numc, uint32_t max_clusters) 78 { 79 uint32_t clusters = 0; 80 fat_cluster_t clst = firstc, clst_last1 = FAT_CLST_LAST1(bs); 81 fat_cluster_t clst_bad = FAT_CLST_BAD(bs); 90 82 int rc; 91 83 … … 99 91 } 100 92 101 while (clst < FAT_CLST_LAST1 && clusters < max_clusters) { 102 aoff64_t fsec; /* sector offset relative to FAT1 */ 103 unsigned fidx; /* FAT1 entry index */ 104 93 while (clst < clst_last1 && clusters < max_clusters) { 105 94 assert(clst >= FAT_CLST_FIRST); 106 95 if (lastc) 107 96 *lastc = clst; /* remember the last cluster number */ 108 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs); 109 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t)); 97 110 98 /* read FAT1 */ 111 rc = block_get(&b, devmap_handle, RSCNT(bs) + fsec, 112 BLOCK_FLAGS_NONE); 113 if (rc != EOK) 114 return rc; 115 clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); 116 assert(clst != FAT_CLST_BAD); 117 rc = block_put(b); 118 if (rc != EOK) 119 return rc; 99 rc = fat_get_cluster(bs, service_id, FAT1, clst, &clst); 100 if (rc != EOK) 101 return rc; 102 103 assert(clst != clst_bad); 120 104 clusters++; 121 105 } 122 106 123 if (lastc && clst < FAT_CLST_LAST1)107 if (lastc && clst < clst_last1) 124 108 *lastc = clst; 125 109 if (numc) … … 151 135 return ELIMIT; 152 136 153 if ( nodep->firstc == FAT_CLST_ROOT)137 if (!FAT_IS_FAT32(bs) && nodep->firstc == FAT_CLST_ROOT) 154 138 goto fall_through; 155 139 … … 160 144 * when fortunately we have the last cluster number cached. 161 145 */ 162 return block_get(block, nodep->idx-> devmap_handle,146 return block_get(block, nodep->idx->service_id, 163 147 CLBN2PBN(bs, nodep->lastc_cached_value, bn), flags); 164 148 } … … 174 158 175 159 fall_through: 176 rc = _fat_block_get(block, bs, nodep->idx-> devmap_handle, firstc,160 rc = _fat_block_get(block, bs, nodep->idx->service_id, firstc, 177 161 &currc, relbn, flags); 178 162 if (rc != EOK) 179 163 return rc; 180 164 181 165 /* 182 166 * Update the "current" cluster cache. … … 193 177 * @param block Pointer to a block pointer for storing result. 194 178 * @param bs Buffer holding the boot sector of the file system. 195 * @param devmap_handle Devicehandle of the file system.179 * @param service_id Service ID handle of the file system. 196 180 * @param fcl First cluster used by the file. Can be zero if the file 197 181 * is empty. 198 182 * @param clp If not NULL, address where the cluster containing bn 199 183 * will be stored. 200 * stored 184 * stored 201 185 * @param bn Block number. 202 186 * @param flags Flags passed to libblock. … … 205 189 */ 206 190 int 207 _fat_block_get(block_t **block, fat_bs_t *bs, devmap_handle_t devmap_handle,191 _fat_block_get(block_t **block, fat_bs_t *bs, service_id_t service_id, 208 192 fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags) 209 193 { 210 uint 16_t clusters;211 u nsignedmax_clusters;194 uint32_t clusters; 195 uint32_t max_clusters; 212 196 fat_cluster_t c; 213 197 int rc; … … 219 203 return ELIMIT; 220 204 221 if ( fcl == FAT_CLST_ROOT) {205 if (!FAT_IS_FAT32(bs) && fcl == FAT_CLST_ROOT) { 222 206 /* root directory special case */ 223 207 assert(bn < RDS(bs)); 224 rc = block_get(block, devmap_handle,208 rc = block_get(block, service_id, 225 209 RSCNT(bs) + FATCNT(bs) * SF(bs) + bn, flags); 226 210 return rc; … … 228 212 229 213 max_clusters = bn / SPC(bs); 230 rc = fat_cluster_walk(bs, devmap_handle, fcl, &c, &clusters, max_clusters);214 rc = fat_cluster_walk(bs, service_id, fcl, &c, &clusters, max_clusters); 231 215 if (rc != EOK) 232 216 return rc; 233 217 assert(clusters == max_clusters); 234 218 235 rc = block_get(block, devmap_handle, CLBN2PBN(bs, c, bn), flags);219 rc = block_get(block, service_id, CLBN2PBN(bs, c, bn), flags); 236 220 237 221 if (clp) … … 253 237 * @return EOK on success or a negative error code. 254 238 */ 255 int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos) 239 int 240 fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos) 256 241 { 257 242 block_t *b; … … 275 260 return rc; 276 261 } 277 262 278 263 if (o >= pos) 279 264 return EOK; 280 265 281 266 /* zero out the initial part of the new cluster chain */ 282 267 for (o = boundary; o < pos; o += BPS(bs)) { 283 rc = _fat_block_get(&b, bs, nodep->idx-> devmap_handle, mcl,268 rc = _fat_block_get(&b, bs, nodep->idx->service_id, mcl, 284 269 NULL, (o - boundary) / BPS(bs), BLOCK_FLAGS_NOREAD); 285 270 if (rc != EOK) … … 298 283 * 299 284 * @param bs Buffer holding the boot sector for the file system. 300 * @param devmap_handle Device handlefor the file system.285 * @param service_id Service ID for the file system. 301 286 * @param clst Cluster which to get. 302 287 * @param value Output argument holding the value of the cluster. … … 304 289 * @return EOK or a negative error code. 305 290 */ 306 int307 fat_get_cluster (fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,291 static int 292 fat_get_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 308 293 fat_cluster_t clst, fat_cluster_t *value) 309 294 { 310 block_t *b; 311 fat_cluster_t *cp; 312 int rc; 313 314 rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno + 315 (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE); 295 block_t *b, *b1; 296 uint16_t byte1, byte2; 297 aoff64_t offset; 298 int rc; 299 300 offset = (clst + clst / 2); 301 if (offset / BPS(bs) >= SF(bs)) 302 return ERANGE; 303 304 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno + 305 offset / BPS(bs), BLOCK_FLAGS_NONE); 316 306 if (rc != EOK) 317 307 return rc; 318 cp = (fat_cluster_t *)b->data + 319 clst % (BPS(bs) / sizeof(fat_cluster_t)); 320 *value = uint16_t_le2host(*cp); 308 309 byte1 = ((uint8_t *) b->data)[offset % BPS(bs)]; 310 /* This cluster access spans a sector boundary. Check only for FAT12 */ 311 if ((offset % BPS(bs)) + 1 == BPS(bs)) { 312 /* Is this the last sector of FAT? */ 313 if (offset / BPS(bs) < SF(bs)) { 314 /* No, read the next sector */ 315 rc = block_get(&b1, service_id, 1 + RSCNT(bs) + 316 SF(bs) * fatno + offset / BPS(bs), 317 BLOCK_FLAGS_NONE); 318 if (rc != EOK) { 319 block_put(b); 320 return rc; 321 } 322 /* 323 * Combining value with last byte of current sector and 324 * first byte of next sector 325 */ 326 byte2 = ((uint8_t*) b1->data)[0]; 327 328 rc = block_put(b1); 329 if (rc != EOK) { 330 block_put(b); 331 return rc; 332 } 333 } else { 334 /* Yes. This is the last sector of FAT */ 335 block_put(b); 336 return ERANGE; 337 } 338 } else 339 byte2 = ((uint8_t *) b->data)[(offset % BPS(bs)) + 1]; 340 341 *value = uint16_t_le2host(byte1 | (byte2 << 8)); 342 if (IS_ODD(clst)) 343 *value = (*value) >> 4; 344 else 345 *value = (*value) & FAT12_MASK; 346 321 347 rc = block_put(b); 322 348 323 349 return rc; 324 350 } 325 351 352 /** Get cluster from the first FAT. 353 * 354 * @param bs Buffer holding the boot sector for the file system. 355 * @param service_id Service ID for the file system. 356 * @param clst Cluster which to get. 357 * @param value Output argument holding the value of the cluster. 358 * 359 * @return EOK or a negative error code. 360 */ 361 static int 362 fat_get_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 363 fat_cluster_t clst, fat_cluster_t *value) 364 { 365 block_t *b; 366 aoff64_t offset; 367 int rc; 368 369 offset = (clst * FAT16_CLST_SIZE); 370 371 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno + 372 offset / BPS(bs), BLOCK_FLAGS_NONE); 373 if (rc != EOK) 374 return rc; 375 376 *value = uint16_t_le2host(*(uint16_t *)(b->data + offset % BPS(bs))); 377 378 rc = block_put(b); 379 380 return rc; 381 } 382 383 /** Get cluster from the first FAT. 384 * 385 * @param bs Buffer holding the boot sector for the file system. 386 * @param service_id Service ID for the file system. 387 * @param clst Cluster which to get. 388 * @param value Output argument holding the value of the cluster. 389 * 390 * @return EOK or a negative error code. 391 */ 392 static int 393 fat_get_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 394 fat_cluster_t clst, fat_cluster_t *value) 395 { 396 block_t *b; 397 aoff64_t offset; 398 int rc; 399 400 offset = (clst * FAT32_CLST_SIZE); 401 402 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno + 403 offset / BPS(bs), BLOCK_FLAGS_NONE); 404 if (rc != EOK) 405 return rc; 406 407 *value = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs))) & 408 FAT32_MASK; 409 410 rc = block_put(b); 411 412 return rc; 413 } 414 415 416 /** Get cluster from the first FAT. 417 * 418 * @param bs Buffer holding the boot sector for the file system. 419 * @param service_id Service ID for the file system. 420 * @param clst Cluster which to get. 421 * @param value Output argument holding the value of the cluster. 422 * 423 * @return EOK or a negative error code. 424 */ 425 int 426 fat_get_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 427 fat_cluster_t clst, fat_cluster_t *value) 428 { 429 int rc; 430 431 assert(fatno < FATCNT(bs)); 432 433 if (FAT_IS_FAT12(bs)) 434 rc = fat_get_cluster_fat12(bs, service_id, fatno, clst, value); 435 else if (FAT_IS_FAT16(bs)) 436 rc = fat_get_cluster_fat16(bs, service_id, fatno, clst, value); 437 else 438 rc = fat_get_cluster_fat32(bs, service_id, fatno, clst, value); 439 440 return rc; 441 } 442 326 443 /** Set cluster in one instance of FAT. 327 444 * 328 445 * @param bs Buffer holding the boot sector for the file system. 329 * @param devmap_handle Device handlefor the file system.446 * @param service_id Service ID for the file system. 330 447 * @param fatno Number of the FAT instance where to make the change. 331 448 * @param clst Cluster which is to be set. … … 334 451 * @return EOK on success or a negative error code. 335 452 */ 336 int337 fat_set_cluster (fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,453 static int 454 fat_set_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 338 455 fat_cluster_t clst, fat_cluster_t value) 339 456 { 340 block_t *b; 341 fat_cluster_t *cp; 342 int rc; 343 344 assert(fatno < FATCNT(bs)); 345 rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno + 346 (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE); 457 block_t *b, *b1 = NULL; 458 aoff64_t offset; 459 uint16_t byte1, byte2; 460 int rc; 461 462 offset = (clst + clst / 2); 463 if (offset / BPS(bs) >= SF(bs)) 464 return ERANGE; 465 466 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno + 467 offset / BPS(bs), BLOCK_FLAGS_NONE); 347 468 if (rc != EOK) 348 469 return rc; 349 cp = (fat_cluster_t *)b->data + 350 clst % (BPS(bs) / sizeof(fat_cluster_t)); 351 *cp = host2uint16_t_le(value); 352 b->dirty = true; /* need to sync block */ 470 471 byte1 = ((uint8_t*) b->data)[offset % BPS(bs)]; 472 bool border = false; 473 /* This cluster access spans a sector boundary. */ 474 if ((offset % BPS(bs)) + 1 == BPS(bs)) { 475 /* Is it the last sector of FAT? */ 476 if (offset / BPS(bs) < SF(bs)) { 477 /* No, read the next sector */ 478 rc = block_get(&b1, service_id, 1 + RSCNT(bs) + 479 SF(bs) * fatno + offset / BPS(bs), 480 BLOCK_FLAGS_NONE); 481 if (rc != EOK) { 482 block_put(b); 483 return rc; 484 } 485 /* 486 * Combining value with last byte of current sector and 487 * first byte of next sector 488 */ 489 byte2 = ((uint8_t *) b1->data)[0]; 490 border = true; 491 } else { 492 /* Yes. This is the last sector of FAT */ 493 block_put(b); 494 return ERANGE; 495 } 496 } else 497 byte2 = ((uint8_t*) b->data)[(offset % BPS(bs)) + 1]; 498 499 if (IS_ODD(clst)) { 500 byte1 &= 0x0f; 501 byte2 = 0; 502 value = (value << 4); 503 } else { 504 byte1 = 0; 505 byte2 &= 0xf0; 506 value &= FAT12_MASK; 507 } 508 509 byte1 = byte1 | (value & 0xff); 510 byte2 = byte2 | (value >> 8); 511 512 ((uint8_t *) b->data)[(offset % BPS(bs))] = byte1; 513 if (border) { 514 ((uint8_t *) b1->data)[0] = byte2; 515 516 b1->dirty = true; 517 rc = block_put(b1); 518 if (rc != EOK) { 519 block_put(b); 520 return rc; 521 } 522 } else 523 ((uint8_t *) b->data)[(offset % BPS(bs)) + 1] = byte2; 524 525 b->dirty = true; /* need to sync block */ 353 526 rc = block_put(b); 527 354 528 return rc; 355 529 } 356 530 531 /** Set cluster in one instance of FAT. 532 * 533 * @param bs Buffer holding the boot sector for the file system. 534 * @param service_id Service ID for the file system. 535 * @param fatno Number of the FAT instance where to make the change. 536 * @param clst Cluster which is to be set. 537 * @param value Value to set the cluster with. 538 * 539 * @return EOK on success or a negative error code. 540 */ 541 static int 542 fat_set_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 543 fat_cluster_t clst, fat_cluster_t value) 544 { 545 block_t *b; 546 aoff64_t offset; 547 int rc; 548 549 offset = (clst * FAT16_CLST_SIZE); 550 551 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno + 552 offset / BPS(bs), BLOCK_FLAGS_NONE); 553 if (rc != EOK) 554 return rc; 555 556 *(uint16_t *)(b->data + offset % BPS(bs)) = host2uint16_t_le(value); 557 558 b->dirty = true; /* need to sync block */ 559 rc = block_put(b); 560 561 return rc; 562 } 563 564 /** Set cluster in one instance of FAT. 565 * 566 * @param bs Buffer holding the boot sector for the file system. 567 * @param service_id Service ID for the file system. 568 * @param fatno Number of the FAT instance where to make the change. 569 * @param clst Cluster which is to be set. 570 * @param value Value to set the cluster with. 571 * 572 * @return EOK on success or a negative error code. 573 */ 574 static int 575 fat_set_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 576 fat_cluster_t clst, fat_cluster_t value) 577 { 578 block_t *b; 579 aoff64_t offset; 580 int rc; 581 fat_cluster_t temp; 582 583 offset = (clst * FAT32_CLST_SIZE); 584 585 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno + 586 offset / BPS(bs), BLOCK_FLAGS_NONE); 587 if (rc != EOK) 588 return rc; 589 590 temp = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs))); 591 temp &= 0xf0000000; 592 temp |= (value & FAT32_MASK); 593 *(uint32_t *)(b->data + offset % BPS(bs)) = host2uint32_t_le(temp); 594 595 b->dirty = true; /* need to sync block */ 596 rc = block_put(b); 597 598 return rc; 599 } 600 601 /** Set cluster in one instance of FAT. 602 * 603 * @param bs Buffer holding the boot sector for the file system. 604 * @param service_id Device service ID for the file system. 605 * @param fatno Number of the FAT instance where to make the change. 606 * @param clst Cluster which is to be set. 607 * @param value Value to set the cluster with. 608 * 609 * @return EOK on success or a negative error code. 610 */ 611 int 612 fat_set_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 613 fat_cluster_t clst, fat_cluster_t value) 614 { 615 int rc; 616 617 assert(fatno < FATCNT(bs)); 618 619 if (FAT_IS_FAT12(bs)) 620 rc = fat_set_cluster_fat12(bs, service_id, fatno, clst, value); 621 else if (FAT_IS_FAT16(bs)) 622 rc = fat_set_cluster_fat16(bs, service_id, fatno, clst, value); 623 else 624 rc = fat_set_cluster_fat32(bs, service_id, fatno, clst, value); 625 626 return rc; 627 } 628 357 629 /** Replay the allocatoin of clusters in all shadow instances of FAT. 358 630 * 359 631 * @param bs Buffer holding the boot sector of the file system. 360 * @param devmap_handle Device handleof the file system.632 * @param service_id Service ID of the file system. 361 633 * @param lifo Chain of allocated clusters. 362 634 * @param nclsts Number of clusters in the lifo chain. … … 364 636 * @return EOK on success or a negative error code. 365 637 */ 366 int fat_alloc_shadow_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle,638 int fat_alloc_shadow_clusters(fat_bs_t *bs, service_id_t service_id, 367 639 fat_cluster_t *lifo, unsigned nclsts) 368 640 { 369 641 uint8_t fatno; 370 642 unsigned c; 371 int rc; 372 373 for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) { 643 fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs); 644 int rc; 645 646 for (fatno = FAT1 + 1; fatno < FATCNT(bs); fatno++) { 374 647 for (c = 0; c < nclsts; c++) { 375 rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c],376 c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);648 rc = fat_set_cluster(bs, service_id, fatno, lifo[c], 649 c == 0 ? clst_last1 : lifo[c - 1]); 377 650 if (rc != EOK) 378 651 return rc; … … 391 664 * 392 665 * @param bs Buffer holding the boot sector of the file system. 393 * @param devmap_handle Device handleof the file system.666 * @param service_id Device service ID of the file system. 394 667 * @param nclsts Number of clusters to allocate. 395 668 * @param mcl Output parameter where the first cluster in the chain … … 401 674 */ 402 675 int 403 fat_alloc_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned nclsts,676 fat_alloc_clusters(fat_bs_t *bs, service_id_t service_id, unsigned nclsts, 404 677 fat_cluster_t *mcl, fat_cluster_t *lcl) 405 678 { 406 block_t *blk; 407 fat_cluster_t *lifo; /* stack for storing free cluster numbers */ 408 unsigned found = 0; /* top of the free cluster number stack */ 409 unsigned b, c, cl; 410 int rc; 679 fat_cluster_t *lifo; /* stack for storing free cluster numbers */ 680 unsigned found = 0; /* top of the free cluster number stack */ 681 fat_cluster_t clst, value, clst_last1 = FAT_CLST_LAST1(bs); 682 int rc = EOK; 411 683 412 684 lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t)); … … 418 690 */ 419 691 fibril_mutex_lock(&fat_alloc_lock); 420 for (b = 0, cl = 0; b < SF(bs); b++) { 421 rc = block_get(&blk, devmap_handle, RSCNT(bs) + b, 422 BLOCK_FLAGS_NONE); 423 if (rc != EOK) 424 goto error; 425 for (c = 0; c < BPS(bs) / sizeof(fat_cluster_t); c++, cl++) { 692 for (clst = FAT_CLST_FIRST; clst < CC(bs) + 2 && found < nclsts; 693 clst++) { 694 rc = fat_get_cluster(bs, service_id, FAT1, clst, &value); 695 if (rc != EOK) 696 break; 697 698 if (value == FAT_CLST_RES0) { 426 699 /* 427 * Check if the entire cluster is physically there. 428 * This check becomes necessary when the file system is 429 * created with fewer total sectors than how many is 430 * inferred from the size of the file allocation table 431 * or when the last cluster ends beyond the end of the 432 * device. 700 * The cluster is free. Put it into our stack 701 * of found clusters and mark it as non-free. 433 702 */ 434 if ((cl >= FAT_CLST_FIRST) && 435 CLBN2PBN(bs, cl, SPC(bs) - 1) >= TS(bs)) { 436 rc = block_put(blk); 437 if (rc != EOK) 438 goto error; 439 goto out; 440 } 441 442 fat_cluster_t *clst = (fat_cluster_t *)blk->data + c; 443 if (uint16_t_le2host(*clst) == FAT_CLST_RES0) { 444 /* 445 * The cluster is free. Put it into our stack 446 * of found clusters and mark it as non-free. 447 */ 448 lifo[found] = cl; 449 *clst = (found == 0) ? 450 host2uint16_t_le(FAT_CLST_LAST1) : 451 host2uint16_t_le(lifo[found - 1]); 452 blk->dirty = true; /* need to sync block */ 453 if (++found == nclsts) { 454 /* we are almost done */ 455 rc = block_put(blk); 456 if (rc != EOK) 457 goto error; 458 /* update the shadow copies of FAT */ 459 rc = fat_alloc_shadow_clusters(bs, 460 devmap_handle, lifo, nclsts); 461 if (rc != EOK) 462 goto error; 463 *mcl = lifo[found - 1]; 464 *lcl = lifo[0]; 465 free(lifo); 466 fibril_mutex_unlock(&fat_alloc_lock); 467 return EOK; 468 } 469 } 703 lifo[found] = clst; 704 rc = fat_set_cluster(bs, service_id, FAT1, clst, 705 (found == 0) ? clst_last1 : lifo[found - 1]); 706 if (rc != EOK) 707 break; 708 709 found++; 470 710 } 471 rc = block_put(blk); 472 if (rc != EOK) { 473 error: 711 } 712 713 if (rc == EOK && found == nclsts) { 714 rc = fat_alloc_shadow_clusters(bs, service_id, lifo, nclsts); 715 if (rc == EOK) { 716 *mcl = lifo[found - 1]; 717 *lcl = lifo[0]; 718 free(lifo); 474 719 fibril_mutex_unlock(&fat_alloc_lock); 475 free(lifo); 476 return rc; 720 return EOK; 477 721 } 478 722 } 479 out: 723 724 /* If something wrong - free the clusters */ 725 while (found--) { 726 (void) fat_set_cluster(bs, service_id, FAT1, lifo[found], 727 FAT_CLST_RES0); 728 } 729 730 free(lifo); 480 731 fibril_mutex_unlock(&fat_alloc_lock); 481 732 482 /*483 * We could not find enough clusters. Now we need to free the clusters484 * we have allocated so far.485 */486 while (found--) {487 rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found],488 FAT_CLST_RES0);489 if (rc != EOK) {490 free(lifo);491 return rc;492 }493 }494 495 free(lifo);496 733 return ENOSPC; 497 734 } … … 500 737 * 501 738 * @param bs Buffer hodling the boot sector of the file system. 502 * @param devmap_handle Device handleof the file system.739 * @param service_id Device service ID of the file system. 503 740 * @param firstc First cluster in the chain which is to be freed. 504 741 * … … 506 743 */ 507 744 int 508 fat_free_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc)745 fat_free_clusters(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc) 509 746 { 510 747 unsigned fatno; 511 fat_cluster_t nextc ;748 fat_cluster_t nextc, clst_bad = FAT_CLST_BAD(bs); 512 749 int rc; 513 750 514 751 /* Mark all clusters in the chain as free in all copies of FAT. */ 515 while (firstc < FAT_CLST_LAST1) { 516 assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD); 517 rc = fat_get_cluster(bs, devmap_handle, FAT1, firstc, &nextc); 518 if (rc != EOK) 519 return rc; 520 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 521 rc = fat_set_cluster(bs, devmap_handle, fatno, firstc, 752 while (firstc < FAT_CLST_LAST1(bs)) { 753 assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad); 754 755 rc = fat_get_cluster(bs, service_id, FAT1, firstc, &nextc); 756 if (rc != EOK) 757 return rc; 758 759 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) { 760 rc = fat_set_cluster(bs, service_id, fatno, firstc, 522 761 FAT_CLST_RES0); 523 762 if (rc != EOK) … … 540 779 * @return EOK on success or a negative error code. 541 780 */ 542 int 543 fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, 781 int fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, 544 782 fat_cluster_t lcl) 545 783 { 546 devmap_handle_t devmap_handle = nodep->idx->devmap_handle;784 service_id_t service_id = nodep->idx->service_id; 547 785 fat_cluster_t lastc; 548 786 uint8_t fatno; … … 558 796 nodep->lastc_cached_valid = false; 559 797 } else { 560 rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc,561 &lastc, NULL, (uint 16_t) -1);798 rc = fat_cluster_walk(bs, service_id, nodep->firstc, 799 &lastc, NULL, (uint32_t) -1); 562 800 if (rc != EOK) 563 801 return rc; 564 802 } 565 803 566 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {567 rc = fat_set_cluster(bs, nodep->idx-> devmap_handle, fatno,568 lastc, mcl);804 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) { 805 rc = fat_set_cluster(bs, nodep->idx->service_id, 806 fatno, lastc, mcl); 569 807 if (rc != EOK) 570 808 return rc; … … 590 828 int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl) 591 829 { 592 int rc; 593 devmap_handle_t devmap_handle = nodep->idx->devmap_handle; 830 fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs); 831 int rc; 832 service_id_t service_id = nodep->idx->service_id; 594 833 595 834 /* … … 602 841 if (lcl == FAT_CLST_RES0) { 603 842 /* The node will have zero size and no clusters allocated. */ 604 rc = fat_free_clusters(bs, devmap_handle, nodep->firstc);843 rc = fat_free_clusters(bs, service_id, nodep->firstc); 605 844 if (rc != EOK) 606 845 return rc; … … 611 850 unsigned fatno; 612 851 613 rc = fat_get_cluster(bs, devmap_handle, FAT1, lcl, &nextc);852 rc = fat_get_cluster(bs, service_id, FAT1, lcl, &nextc); 614 853 if (rc != EOK) 615 854 return rc; 616 855 617 856 /* Terminate the cluster chain in all copies of FAT. */ 618 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {619 rc = fat_set_cluster(bs, devmap_handle, fatno, lcl,620 FAT_CLST_LAST1);857 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) { 858 rc = fat_set_cluster(bs, service_id, fatno, lcl, 859 clst_last1); 621 860 if (rc != EOK) 622 861 return rc; … … 624 863 625 864 /* Free all following clusters. */ 626 rc = fat_free_clusters(bs, devmap_handle, nextc);865 rc = fat_free_clusters(bs, service_id, nextc); 627 866 if (rc != EOK) 628 867 return rc; … … 639 878 640 879 int 641 fat_zero_cluster(struct fat_bs *bs, devmap_handle_t devmap_handle, fat_cluster_t c)880 fat_zero_cluster(struct fat_bs *bs, service_id_t service_id, fat_cluster_t c) 642 881 { 643 882 int i; … … 646 885 647 886 for (i = 0; i < SPC(bs); i++) { 648 rc = _fat_block_get(&b, bs, devmap_handle, c, NULL, i,887 rc = _fat_block_get(&b, bs, service_id, c, NULL, i, 649 888 BLOCK_FLAGS_NOREAD); 650 889 if (rc != EOK) … … 666 905 * does not contain a fat file system. 667 906 */ 668 int fat_sanity_check(fat_bs_t *bs, devmap_handle_t devmap_handle)907 int fat_sanity_check(fat_bs_t *bs, service_id_t service_id) 669 908 { 670 909 fat_cluster_t e0, e1; … … 673 912 674 913 /* Check number of FATs. */ 675 if ( bs->fatcnt== 0)914 if (FATCNT(bs) == 0) 676 915 return ENOTSUP; 677 916 678 917 /* Check total number of sectors. */ 679 680 if (bs->totsec16 == 0 && bs->totsec32 == 0) 918 if (TS(bs) == 0) 681 919 return ENOTSUP; 682 920 683 921 if (bs->totsec16 != 0 && bs->totsec32 != 0 && 684 bs->totsec16 != bs->totsec32) 922 bs->totsec16 != bs->totsec32) 685 923 return ENOTSUP; 686 924 … … 690 928 691 929 /* Check number of sectors per FAT. */ 692 if ( bs->sec_per_fat== 0)930 if (SF(bs) == 0) 693 931 return ENOTSUP; 694 932 … … 700 938 * sanitized to support file systems with this property. 701 939 */ 702 if ( (uint16_t_le2host(bs->root_ent_max) * sizeof(fat_dentry_t)) %703 uint16_t_le2host(bs->bps) != 0)940 if (!FAT_IS_FAT32(bs) && 941 (RDE(bs) * sizeof(fat_dentry_t)) % BPS(bs) != 0) 704 942 return ENOTSUP; 705 943 706 944 /* Check signature of each FAT. */ 707 708 for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) { 709 rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0); 945 for (fat_no = 0; fat_no < FATCNT(bs); fat_no++) { 946 rc = fat_get_cluster(bs, service_id, fat_no, 0, &e0); 710 947 if (rc != EOK) 711 948 return EIO; 712 949 713 rc = fat_get_cluster(bs, devmap_handle, fat_no, 1, &e1);950 rc = fat_get_cluster(bs, service_id, fat_no, 1, &e1); 714 951 if (rc != EOK) 715 952 return EIO; 716 953 717 /* Check that first byte of FAT contains the media descriptor. */ 954 /* 955 * Check that first byte of FAT contains the media descriptor. 956 */ 718 957 if ((e0 & 0xff) != bs->mdesc) 719 958 return ENOTSUP; … … 723 962 * set to one. 724 963 */ 725 if ((e0 >> 8) != 0xff || e1 != 0xffff) 964 if (!FAT_IS_FAT12(bs) && 965 ((e0 >> 8) != (FAT_MASK(bs) >> 8) || e1 != FAT_MASK(bs))) 726 966 return ENOTSUP; 727 967 } … … 732 972 /** 733 973 * @} 734 */ 974 */ -
uspace/srv/fs/fat/fat_fat.h
rd2c67e7 r8ff0bd2 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 29 30 /** @addtogroup fs 30 31 * @{ 31 */ 32 */ 32 33 33 34 #ifndef FAT_FAT_FAT_H_ … … 40 41 #define FAT1 0 41 42 42 #define FAT_CLST_RES0 0x0000 43 #define FAT_CLST_RES1 0x0001 44 #define FAT_CLST_FIRST 0x0002 45 #define FAT_CLST_BAD 0xfff7 46 #define FAT_CLST_LAST1 0xfff8 47 #define FAT_CLST_LAST8 0xffff 43 #define FAT_CLST_RES0 0 44 #define FAT_CLST_RES1 1 45 #define FAT_CLST_FIRST 2 46 47 #define FAT32_CLST_BAD 0x0ffffff7 48 #define FAT32_CLST_LAST1 0x0ffffff8 49 #define FAT32_CLST_LAST8 0x0fffffff 50 51 #define FAT12_MASK 0x0fff 52 #define FAT16_MASK 0xffff 53 #define FAT32_MASK 0x0fffffff 54 55 #define FAT12_CLST_MAX 4085 56 #define FAT16_CLST_MAX 65525 57 58 /* Size in bytes for cluster value of FAT */ 59 #define FAT12_CLST_SIZE 2 60 #define FAT16_CLST_SIZE 2 61 #define FAT32_CLST_SIZE 4 48 62 49 63 /* internally used to mark root directory's parent */ … … 52 66 #define FAT_CLST_ROOT FAT_CLST_RES1 53 67 68 /* 69 * Convenience macros for computing some frequently used values from the 70 * primitive boot sector members. 71 */ 72 #define RDS(bs) ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \ 73 (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0) 74 #define SSA(bs) (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs)) 75 #define DS(bs) (TS(bs) - SSA(bs)) 76 #define CC(bs) (DS(bs) / SPC(bs)) 77 78 #define CLBN2PBN(bs, cl, bn) \ 79 (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs))) 80 81 #define FAT_IS_FAT12(bs) (CC(bs) < FAT12_CLST_MAX) 82 #define FAT_IS_FAT16(bs) \ 83 ((CC(bs) >= FAT12_CLST_MAX) && (CC(bs) < FAT16_CLST_MAX)) 84 #define FAT_IS_FAT32(bs) (CC(bs) >= FAT16_CLST_MAX) 85 86 #define FAT_CLST_SIZE(bs) \ 87 (FAT_IS_FAT32(bs) ? FAT32_CLST_SIZE : FAT16_CLST_SIZE) 88 89 #define FAT_MASK(bs) \ 90 (FAT_IS_FAT12(bs) ? FAT12_MASK : \ 91 (FAT_IS_FAT32(bs) ? FAT32_MASK : FAT16_MASK)) 92 93 #define FAT_CLST_LAST1(bs) (FAT32_CLST_LAST1 & FAT_MASK((bs))) 94 #define FAT_CLST_LAST8(bs) (FAT32_CLST_LAST8 & FAT_MASK((bs))) 95 #define FAT_CLST_BAD(bs) (FAT32_CLST_BAD & FAT_MASK((bs))) 96 97 #define FAT_ROOT_CLST(bs) \ 98 (FAT_IS_FAT32(bs) ? uint32_t_le2host(bs->fat32.root_cluster) : \ 99 FAT_CLST_ROOT) 100 54 101 /* forward declarations */ 55 102 struct block; … … 57 104 struct fat_bs; 58 105 59 typedef uint 16_t fat_cluster_t;106 typedef uint32_t fat_cluster_t; 60 107 61 #define fat_clusters_get(numc, bs, dh, fc) \62 fat_cluster_walk((bs), ( dh), (fc), NULL, (numc), (uint16_t) -1)63 extern int fat_cluster_walk(struct fat_bs *, devmap_handle_t, fat_cluster_t,64 fat_cluster_t *, uint 16_t *, uint16_t);108 #define fat_clusters_get(numc, bs, sid, fc) \ 109 fat_cluster_walk((bs), (sid), (fc), NULL, (numc), (uint32_t) -1) 110 extern int fat_cluster_walk(struct fat_bs *, service_id_t, fat_cluster_t, 111 fat_cluster_t *, uint32_t *, uint32_t); 65 112 66 113 extern int fat_block_get(block_t **, struct fat_bs *, struct fat_node *, 67 114 aoff64_t, int); 68 extern int _fat_block_get(block_t **, struct fat_bs *, devmap_handle_t,115 extern int _fat_block_get(block_t **, struct fat_bs *, service_id_t, 69 116 fat_cluster_t, fat_cluster_t *, aoff64_t, int); 70 117 … … 73 120 extern int fat_chop_clusters(struct fat_bs *, struct fat_node *, 74 121 fat_cluster_t); 75 extern int fat_alloc_clusters(struct fat_bs *, devmap_handle_t, unsigned,122 extern int fat_alloc_clusters(struct fat_bs *, service_id_t, unsigned, 76 123 fat_cluster_t *, fat_cluster_t *); 77 extern int fat_free_clusters(struct fat_bs *, devmap_handle_t, fat_cluster_t);78 extern int fat_alloc_shadow_clusters(struct fat_bs *, devmap_handle_t,124 extern int fat_free_clusters(struct fat_bs *, service_id_t, fat_cluster_t); 125 extern int fat_alloc_shadow_clusters(struct fat_bs *, service_id_t, 79 126 fat_cluster_t *, unsigned); 80 extern int fat_get_cluster(struct fat_bs *, devmap_handle_t, unsigned,127 extern int fat_get_cluster(struct fat_bs *, service_id_t, unsigned, 81 128 fat_cluster_t, fat_cluster_t *); 82 extern int fat_set_cluster(struct fat_bs *, devmap_handle_t, unsigned,129 extern int fat_set_cluster(struct fat_bs *, service_id_t, unsigned, 83 130 fat_cluster_t, fat_cluster_t); 84 131 extern int fat_fill_gap(struct fat_bs *, struct fat_node *, fat_cluster_t, 85 132 aoff64_t); 86 extern int fat_zero_cluster(struct fat_bs *, devmap_handle_t, fat_cluster_t);87 extern int fat_sanity_check(struct fat_bs *, devmap_handle_t);133 extern int fat_zero_cluster(struct fat_bs *, service_id_t, fat_cluster_t); 134 extern int fat_sanity_check(struct fat_bs *, service_id_t); 88 135 89 136 #endif -
uspace/srv/fs/fat/fat_idx.c
rd2c67e7 r8ff0bd2 59 59 typedef struct { 60 60 link_t link; 61 devmap_handle_t devmap_handle;61 service_id_t service_id; 62 62 63 63 /** Next unassigned index. */ 64 fs_index_t 64 fs_index_t next; 65 65 /** Number of remaining unassigned indices. */ 66 uint64_t 66 uint64_t remaining; 67 67 68 68 /** Sorted list of intervals of freed indices. */ 69 li nk_t freed_head;69 list_t freed_list; 70 70 } unused_t; 71 71 … … 74 74 75 75 /** List of unused structures. */ 76 static LIST_INITIALIZE(unused_ head);77 78 static void unused_initialize(unused_t *u, devmap_handle_t devmap_handle)76 static LIST_INITIALIZE(unused_list); 77 78 static void unused_initialize(unused_t *u, service_id_t service_id) 79 79 { 80 80 link_initialize(&u->link); 81 u-> devmap_handle = devmap_handle;81 u->service_id = service_id; 82 82 u->next = 0; 83 83 u->remaining = ((uint64_t)((fs_index_t)-1)) + 1; 84 list_initialize(&u->freed_ head);85 } 86 87 static unused_t *unused_find( devmap_handle_t devmap_handle, bool lock)84 list_initialize(&u->freed_list); 85 } 86 87 static unused_t *unused_find(service_id_t service_id, bool lock) 88 88 { 89 89 unused_t *u; 90 link_t *l;91 90 92 91 if (lock) 93 92 fibril_mutex_lock(&unused_lock); 94 for (l = unused_head.next; l != &unused_head; l = l->next) { 93 94 list_foreach(unused_list, l) { 95 95 u = list_get_instance(l, unused_t, link); 96 if (u-> devmap_handle == devmap_handle)96 if (u->service_id == service_id) 97 97 return u; 98 98 } 99 99 100 if (lock) 100 101 fibril_mutex_unlock(&unused_lock); … … 107 108 /** 108 109 * Global hash table of all used fat_idx_t structures. 109 * The index structures are hashed by the devmap_handle, parent node's first110 * The index structures are hashed by the service_id, parent node's first 110 111 * cluster and index within the parent directory. 111 112 */ … … 115 116 #define UPH_BUCKETS (1 << UPH_BUCKETS_LOG) 116 117 117 #define UPH_ DH_KEY 0118 #define UPH_SID_KEY 0 118 119 #define UPH_PFC_KEY 1 119 120 #define UPH_PDI_KEY 2 … … 121 122 static hash_index_t pos_hash(unsigned long key[]) 122 123 { 123 devmap_handle_t devmap_handle = (devmap_handle_t)key[UPH_DH_KEY];124 service_id_t service_id = (service_id_t)key[UPH_SID_KEY]; 124 125 fat_cluster_t pfc = (fat_cluster_t)key[UPH_PFC_KEY]; 125 126 unsigned pdi = (unsigned)key[UPH_PDI_KEY]; … … 141 142 h |= (pdi & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) << 142 143 (UPH_BUCKETS_LOG / 2); 143 h |= ( devmap_handle& ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) <<144 h |= (service_id & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) << 144 145 (3 * (UPH_BUCKETS_LOG / 4)); 145 146 … … 149 150 static int pos_compare(unsigned long key[], hash_count_t keys, link_t *item) 150 151 { 151 devmap_handle_t devmap_handle = (devmap_handle_t)key[UPH_DH_KEY];152 service_id_t service_id = (service_id_t)key[UPH_SID_KEY]; 152 153 fat_cluster_t pfc; 153 154 unsigned pdi; … … 156 157 switch (keys) { 157 158 case 1: 158 return ( devmap_handle == fidx->devmap_handle);159 return (service_id == fidx->service_id); 159 160 case 3: 160 161 pfc = (fat_cluster_t) key[UPH_PFC_KEY]; 161 162 pdi = (unsigned) key[UPH_PDI_KEY]; 162 return ( devmap_handle == fidx->devmap_handle) && (pfc == fidx->pfc) &&163 return (service_id == fidx->service_id) && (pfc == fidx->pfc) && 163 164 (pdi == fidx->pdi); 164 165 default: … … 182 183 /** 183 184 * Global hash table of all used fat_idx_t structures. 184 * The index structures are hashed by the devmap_handleand index.185 * The index structures are hashed by the service_id and index. 185 186 */ 186 187 static hash_table_t ui_hash; … … 189 190 #define UIH_BUCKETS (1 << UIH_BUCKETS_LOG) 190 191 191 #define UIH_ DH_KEY 0192 #define UIH_SID_KEY 0 192 193 #define UIH_INDEX_KEY 1 193 194 194 195 static hash_index_t idx_hash(unsigned long key[]) 195 196 { 196 devmap_handle_t devmap_handle = (devmap_handle_t)key[UIH_DH_KEY];197 service_id_t service_id = (service_id_t)key[UIH_SID_KEY]; 197 198 fs_index_t index = (fs_index_t)key[UIH_INDEX_KEY]; 198 199 199 200 hash_index_t h; 200 201 201 h = devmap_handle& ((1 << (UIH_BUCKETS_LOG / 2)) - 1);202 h = service_id & ((1 << (UIH_BUCKETS_LOG / 2)) - 1); 202 203 h |= (index & ((1 << (UIH_BUCKETS_LOG / 2)) - 1)) << 203 204 (UIH_BUCKETS_LOG / 2); … … 208 209 static int idx_compare(unsigned long key[], hash_count_t keys, link_t *item) 209 210 { 210 devmap_handle_t devmap_handle = (devmap_handle_t)key[UIH_DH_KEY];211 service_id_t service_id = (service_id_t)key[UIH_SID_KEY]; 211 212 fs_index_t index; 212 213 fat_idx_t *fidx = list_get_instance(item, fat_idx_t, uih_link); … … 214 215 switch (keys) { 215 216 case 1: 216 return ( devmap_handle == fidx->devmap_handle);217 return (service_id == fidx->service_id); 217 218 case 2: 218 219 index = (fs_index_t) key[UIH_INDEX_KEY]; 219 return ( devmap_handle == fidx->devmap_handle) &&220 return (service_id == fidx->service_id) && 220 221 (index == fidx->index); 221 222 default: … … 240 241 241 242 /** Allocate a VFS index which is not currently in use. */ 242 static bool fat_index_alloc( devmap_handle_t devmap_handle, fs_index_t *index)243 static bool fat_index_alloc(service_id_t service_id, fs_index_t *index) 243 244 { 244 245 unused_t *u; 245 246 246 247 assert(index); 247 u = unused_find( devmap_handle, true);248 u = unused_find(service_id, true); 248 249 if (!u) 249 250 return false; 250 251 251 if (list_empty(&u->freed_ head)) {252 if (list_empty(&u->freed_list)) { 252 253 if (u->remaining) { 253 254 /* … … 262 263 } else { 263 264 /* There are some freed indices which we can reuse. */ 264 freed_t *f = list_get_instance( u->freed_head.next, freed_t,265 link);265 freed_t *f = list_get_instance(list_first(&u->freed_list), 266 freed_t, link); 266 267 *index = f->first; 267 268 if (f->first++ == f->last) { … … 302 303 303 304 /** Free a VFS index, which is no longer in use. */ 304 static void fat_index_free( devmap_handle_t devmap_handle, fs_index_t index)305 static void fat_index_free(service_id_t service_id, fs_index_t index) 305 306 { 306 307 unused_t *u; 307 308 308 u = unused_find( devmap_handle, true);309 u = unused_find(service_id, true); 309 310 assert(u); 310 311 … … 320 321 link_t *lnk; 321 322 freed_t *n; 322 for (lnk = u->freed_ head.next; lnk != &u->freed_head;323 for (lnk = u->freed_list.head.next; lnk != &u->freed_list.head; 323 324 lnk = lnk->next) { 324 325 freed_t *f = list_get_instance(lnk, freed_t, link); 325 326 if (f->first == index + 1) { 326 327 f->first--; 327 if (lnk->prev != &u->freed_ head)328 if (lnk->prev != &u->freed_list.head) 328 329 try_coalesce_intervals(lnk->prev, lnk, 329 330 lnk); … … 333 334 if (f->last == index - 1) { 334 335 f->last++; 335 if (lnk->next != &u->freed_ head)336 if (lnk->next != &u->freed_list.head) 336 337 try_coalesce_intervals(lnk, lnk->next, 337 338 lnk); … … 359 360 n->first = index; 360 361 n->last = index; 361 list_append(&n->link, &u->freed_ head);362 list_append(&n->link, &u->freed_list); 362 363 } 363 364 fibril_mutex_unlock(&unused_lock); 364 365 } 365 366 366 static int fat_idx_create(fat_idx_t **fidxp, devmap_handle_t devmap_handle)367 static int fat_idx_create(fat_idx_t **fidxp, service_id_t service_id) 367 368 { 368 369 fat_idx_t *fidx; … … 371 372 if (!fidx) 372 373 return ENOMEM; 373 if (!fat_index_alloc( devmap_handle, &fidx->index)) {374 if (!fat_index_alloc(service_id, &fidx->index)) { 374 375 free(fidx); 375 376 return ENOSPC; … … 379 380 link_initialize(&fidx->uih_link); 380 381 fibril_mutex_initialize(&fidx->lock); 381 fidx-> devmap_handle = devmap_handle;382 fidx->service_id = service_id; 382 383 fidx->pfc = FAT_CLST_RES0; /* no parent yet */ 383 384 fidx->pdi = 0; … … 388 389 } 389 390 390 int fat_idx_get_new(fat_idx_t **fidxp, devmap_handle_t devmap_handle)391 int fat_idx_get_new(fat_idx_t **fidxp, service_id_t service_id) 391 392 { 392 393 fat_idx_t *fidx; … … 394 395 395 396 fibril_mutex_lock(&used_lock); 396 rc = fat_idx_create(&fidx, devmap_handle);397 rc = fat_idx_create(&fidx, service_id); 397 398 if (rc != EOK) { 398 399 fibril_mutex_unlock(&used_lock); … … 401 402 402 403 unsigned long ikey[] = { 403 [UIH_ DH_KEY] = devmap_handle,404 [UIH_SID_KEY] = service_id, 404 405 [UIH_INDEX_KEY] = fidx->index, 405 406 }; … … 414 415 415 416 fat_idx_t * 416 fat_idx_get_by_pos( devmap_handle_t devmap_handle, fat_cluster_t pfc, unsigned pdi)417 fat_idx_get_by_pos(service_id_t service_id, fat_cluster_t pfc, unsigned pdi) 417 418 { 418 419 fat_idx_t *fidx; 419 420 link_t *l; 420 421 unsigned long pkey[] = { 421 [UPH_ DH_KEY] = devmap_handle,422 [UPH_SID_KEY] = service_id, 422 423 [UPH_PFC_KEY] = pfc, 423 424 [UPH_PDI_KEY] = pdi, … … 431 432 int rc; 432 433 433 rc = fat_idx_create(&fidx, devmap_handle);434 rc = fat_idx_create(&fidx, service_id); 434 435 if (rc != EOK) { 435 436 fibril_mutex_unlock(&used_lock); … … 438 439 439 440 unsigned long ikey[] = { 440 [UIH_ DH_KEY] = devmap_handle,441 [UIH_SID_KEY] = service_id, 441 442 [UIH_INDEX_KEY] = fidx->index, 442 443 }; … … 457 458 { 458 459 unsigned long pkey[] = { 459 [UPH_ DH_KEY] = idx->devmap_handle,460 [UPH_SID_KEY] = idx->service_id, 460 461 [UPH_PFC_KEY] = idx->pfc, 461 462 [UPH_PDI_KEY] = idx->pdi, … … 470 471 { 471 472 unsigned long pkey[] = { 472 [UPH_ DH_KEY] = idx->devmap_handle,473 [UPH_SID_KEY] = idx->service_id, 473 474 [UPH_PFC_KEY] = idx->pfc, 474 475 [UPH_PDI_KEY] = idx->pdi, … … 481 482 482 483 fat_idx_t * 483 fat_idx_get_by_index( devmap_handle_t devmap_handle, fs_index_t index)484 fat_idx_get_by_index(service_id_t service_id, fs_index_t index) 484 485 { 485 486 fat_idx_t *fidx = NULL; 486 487 link_t *l; 487 488 unsigned long ikey[] = { 488 [UIH_ DH_KEY] = devmap_handle,489 [UIH_SID_KEY] = service_id, 489 490 [UIH_INDEX_KEY] = index, 490 491 }; … … 508 509 { 509 510 unsigned long ikey[] = { 510 [UIH_ DH_KEY] = idx->devmap_handle,511 [UIH_SID_KEY] = idx->service_id, 511 512 [UIH_INDEX_KEY] = idx->index, 512 513 }; 513 devmap_handle_t devmap_handle = idx->devmap_handle;514 service_id_t service_id = idx->service_id; 514 515 fs_index_t index = idx->index; 515 516 … … 525 526 fibril_mutex_unlock(&used_lock); 526 527 /* Release the VFS index. */ 527 fat_index_free( devmap_handle, index);528 fat_index_free(service_id, index); 528 529 /* The index structure itself is freed in idx_remove_callback(). */ 529 530 } … … 547 548 } 548 549 549 int fat_idx_init_by_ devmap_handle(devmap_handle_t devmap_handle)550 int fat_idx_init_by_service_id(service_id_t service_id) 550 551 { 551 552 unused_t *u; … … 555 556 if (!u) 556 557 return ENOMEM; 557 unused_initialize(u, devmap_handle);558 unused_initialize(u, service_id); 558 559 fibril_mutex_lock(&unused_lock); 559 if (!unused_find( devmap_handle, false)) {560 list_append(&u->link, &unused_ head);560 if (!unused_find(service_id, false)) { 561 list_append(&u->link, &unused_list); 561 562 } else { 562 563 free(u); … … 567 568 } 568 569 569 void fat_idx_fini_by_ devmap_handle(devmap_handle_t devmap_handle)570 void fat_idx_fini_by_service_id(service_id_t service_id) 570 571 { 571 572 unsigned long ikey[] = { 572 [UIH_ DH_KEY] = devmap_handle573 [UIH_SID_KEY] = service_id 573 574 }; 574 575 unsigned long pkey[] = { 575 [UPH_ DH_KEY] = devmap_handle576 [UPH_SID_KEY] = service_id 576 577 }; 577 578 … … 589 590 * Free the unused and freed structures for this instance. 590 591 */ 591 unused_t *u = unused_find( devmap_handle, true);592 unused_t *u = unused_find(service_id, true); 592 593 assert(u); 593 594 list_remove(&u->link); 594 595 fibril_mutex_unlock(&unused_lock); 595 596 596 while (!list_empty(&u->freed_ head)) {597 while (!list_empty(&u->freed_list)) { 597 598 freed_t *f; 598 f = list_get_instance( u->freed_head.next, freed_t, link);599 f = list_get_instance(list_first(&u->freed_list), freed_t, link); 599 600 list_remove(&f->link); 600 601 free(f); -
uspace/srv/fs/fat/fat_ops.c
rd2c67e7 r8ff0bd2 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 29 30 /** @addtogroup fs 30 31 * @{ 31 */ 32 */ 32 33 33 34 /** … … 39 40 #include "fat_dentry.h" 40 41 #include "fat_fat.h" 42 #include "fat_directory.h" 41 43 #include "../../vfs/vfs.h" 42 44 #include <libfs.h> 43 45 #include <libblock.h> 44 46 #include <ipc/services.h> 45 #include <ipc/ devmap.h>47 #include <ipc/loc.h> 46 48 #include <macros.h> 47 49 #include <async.h> … … 56 58 #include <align.h> 57 59 #include <malloc.h> 60 #include <str.h> 58 61 59 62 #define FAT_NODE(node) ((node) ? (fat_node_t *) (node)->data : NULL) … … 67 70 68 71 /** List of cached free FAT nodes. */ 69 static LIST_INITIALIZE(ffn_ head);72 static LIST_INITIALIZE(ffn_list); 70 73 71 74 /* 72 75 * Forward declarations of FAT libfs operations. 73 76 */ 74 static int fat_root_get(fs_node_t **, devmap_handle_t);77 static int fat_root_get(fs_node_t **, service_id_t); 75 78 static int fat_match(fs_node_t **, fs_node_t *, const char *); 76 static int fat_node_get(fs_node_t **, devmap_handle_t, fs_index_t);79 static int fat_node_get(fs_node_t **, service_id_t, fs_index_t); 77 80 static int fat_node_open(fs_node_t *); 78 81 static int fat_node_put(fs_node_t *); 79 static int fat_create_node(fs_node_t **, devmap_handle_t, int);82 static int fat_create_node(fs_node_t **, service_id_t, int); 80 83 static int fat_destroy_node(fs_node_t *); 81 84 static int fat_link(fs_node_t *, fs_node_t *, const char *); … … 85 88 static aoff64_t fat_size_get(fs_node_t *); 86 89 static unsigned fat_lnkcnt_get(fs_node_t *); 87 static char fat_plb_get_char(unsigned);88 90 static bool fat_is_directory(fs_node_t *); 89 91 static bool fat_is_file(fs_node_t *node); 90 static devmap_handle_t fat_device_get(fs_node_t *node);92 static service_id_t fat_device_get(fs_node_t *node); 91 93 92 94 /* … … 105 107 node->dirty = false; 106 108 node->lastc_cached_valid = false; 107 node->lastc_cached_value = FAT_CLST_LAST1;109 node->lastc_cached_value = 0; 108 110 node->currc_cached_valid = false; 109 111 node->currc_cached_bn = 0; 110 node->currc_cached_value = FAT_CLST_LAST1;112 node->currc_cached_value = 0; 111 113 } 112 114 … … 117 119 fat_dentry_t *d; 118 120 int rc; 119 121 120 122 assert(node->dirty); 121 123 122 bs = block_bb_get(node->idx-> devmap_handle);123 124 bs = block_bb_get(node->idx->service_id); 125 124 126 /* Read the block that contains the dentry of interest. */ 125 rc = _fat_block_get(&b, bs, node->idx-> devmap_handle, node->idx->pfc,127 rc = _fat_block_get(&b, bs, node->idx->service_id, node->idx->pfc, 126 128 NULL, (node->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs), 127 129 BLOCK_FLAGS_NONE); … … 137 139 d->attr = FAT_ATTR_SUBDIR; 138 140 } 139 141 140 142 /* TODO: update other fields? (e.g time fields) */ 141 143 142 144 b->dirty = true; /* need to sync block */ 143 145 rc = block_put(b); … … 145 147 } 146 148 147 static int fat_node_fini_by_devmap_handle(devmap_handle_t devmap_handle) 148 { 149 link_t *lnk; 149 static int fat_node_fini_by_service_id(service_id_t service_id) 150 { 150 151 fat_node_t *nodep; 151 152 int rc; … … 159 160 restart: 160 161 fibril_mutex_lock(&ffn_mutex); 161 for (lnk = ffn_head.next; lnk != &ffn_head; lnk = lnk->next) {162 list_foreach(ffn_list, lnk) { 162 163 nodep = list_get_instance(lnk, fat_node_t, ffn_link); 163 164 if (!fibril_mutex_trylock(&nodep->lock)) { … … 170 171 goto restart; 171 172 } 172 if (nodep->idx-> devmap_handle != devmap_handle) {173 if (nodep->idx->service_id != service_id) { 173 174 fibril_mutex_unlock(&nodep->idx->lock); 174 175 fibril_mutex_unlock(&nodep->lock); … … 196 197 free(nodep); 197 198 198 /* Need to restart because we changed the ffn_headlist. */199 /* Need to restart because we changed ffn_list. */ 199 200 goto restart; 200 201 } … … 211 212 212 213 fibril_mutex_lock(&ffn_mutex); 213 if (!list_empty(&ffn_ head)) {214 if (!list_empty(&ffn_list)) { 214 215 /* Try to use a cached free node structure. */ 215 216 fat_idx_t *idxp_tmp; 216 nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link); 217 nodep = list_get_instance(list_first(&ffn_list), fat_node_t, 218 ffn_link); 217 219 if (!fibril_mutex_trylock(&nodep->lock)) 218 220 goto skip_cache; … … 256 258 fn->data = nodep; 257 259 nodep->bp = fn; 258 260 259 261 *nodepp = nodep; 260 262 return EOK; … … 292 294 * We must instantiate the node from the file system. 293 295 */ 294 296 295 297 assert(idxp->pfc); 296 298 … … 299 301 return rc; 300 302 301 bs = block_bb_get(idxp-> devmap_handle);303 bs = block_bb_get(idxp->service_id); 302 304 303 305 /* Read the block that contains the dentry of interest. */ 304 rc = _fat_block_get(&b, bs, idxp-> devmap_handle, idxp->pfc, NULL,306 rc = _fat_block_get(&b, bs, idxp->service_id, idxp->pfc, NULL, 305 307 (idxp->pdi * sizeof(fat_dentry_t)) / BPS(bs), BLOCK_FLAGS_NONE); 306 308 if (rc != EOK) { … … 310 312 311 313 d = ((fat_dentry_t *)b->data) + (idxp->pdi % DPS(bs)); 314 if (FAT_IS_FAT32(bs)) { 315 nodep->firstc = uint16_t_le2host(d->firstc_lo) | 316 (uint16_t_le2host(d->firstc_hi) << 16); 317 } else 318 nodep->firstc = uint16_t_le2host(d->firstc); 319 312 320 if (d->attr & FAT_ATTR_SUBDIR) { 313 /* 321 /* 314 322 * The only directory which does not have this bit set is the 315 323 * root directory itself. The root directory node is handled … … 317 325 */ 318 326 nodep->type = FAT_DIRECTORY; 327 319 328 /* 320 329 * Unfortunately, the 'size' field of the FAT dentry is not … … 322 331 * size of the directory by walking the FAT. 323 332 */ 324 uint 16_t clusters;325 rc = fat_clusters_get(&clusters, bs, idxp-> devmap_handle,326 uint16_t_le2host(d->firstc));333 uint32_t clusters; 334 rc = fat_clusters_get(&clusters, bs, idxp->service_id, 335 nodep->firstc); 327 336 if (rc != EOK) { 328 337 (void) block_put(b); … … 335 344 nodep->size = uint32_t_le2host(d->size); 336 345 } 337 nodep->firstc = uint16_t_le2host(d->firstc); 346 338 347 nodep->lnkcnt = 1; 339 348 nodep->refcnt = 1; … … 357 366 */ 358 367 359 int fat_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)360 { 361 return fat_node_get(rfn, devmap_handle, 0);368 int fat_root_get(fs_node_t **rfn, service_id_t service_id) 369 { 370 return fat_node_get(rfn, service_id, 0); 362 371 } 363 372 364 373 int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 365 374 { 366 fat_bs_t *bs;367 375 fat_node_t *parentp = FAT_NODE(pfn); 368 char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; 369 unsigned i, j; 370 unsigned blocks; 376 char name[FAT_LFN_NAME_SIZE]; 371 377 fat_dentry_t *d; 372 devmap_handle_t devmap_handle; 373 block_t *b; 378 service_id_t service_id; 374 379 int rc; 375 380 376 381 fibril_mutex_lock(&parentp->idx->lock); 377 devmap_handle = parentp->idx->devmap_handle;382 service_id = parentp->idx->service_id; 378 383 fibril_mutex_unlock(&parentp->idx->lock); 379 380 bs = block_bb_get(devmap_handle); 381 blocks = parentp->size / BPS(bs); 382 for (i = 0; i < blocks; i++) { 383 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 384 if (rc != EOK) 385 return rc; 386 for (j = 0; j < DPS(bs); j++) { 387 d = ((fat_dentry_t *)b->data) + j; 388 switch (fat_classify_dentry(d)) { 389 case FAT_DENTRY_SKIP: 390 case FAT_DENTRY_FREE: 391 continue; 392 case FAT_DENTRY_LAST: 393 /* miss */ 394 rc = block_put(b); 395 *rfn = NULL; 396 return rc; 397 default: 398 case FAT_DENTRY_VALID: 399 fat_dentry_name_get(d, name); 400 break; 384 385 fat_directory_t di; 386 rc = fat_directory_open(parentp, &di); 387 if (rc != EOK) 388 return rc; 389 390 while (fat_directory_read(&di, name, &d) == EOK) { 391 if (fat_dentry_namecmp(name, component) == 0) { 392 /* hit */ 393 fat_node_t *nodep; 394 aoff64_t o = di.pos % 395 (BPS(di.bs) / sizeof(fat_dentry_t)); 396 fat_idx_t *idx = fat_idx_get_by_pos(service_id, 397 parentp->firstc, di.bnum * DPS(di.bs) + o); 398 if (!idx) { 399 /* 400 * Can happen if memory is low or if we 401 * run out of 32-bit indices. 402 */ 403 rc = fat_directory_close(&di); 404 return (rc == EOK) ? ENOMEM : rc; 401 405 } 402 if (fat_dentry_namecmp(name, component) == 0) { 403 /* hit */ 404 fat_node_t *nodep; 405 fat_idx_t *idx = fat_idx_get_by_pos(devmap_handle, 406 parentp->firstc, i * DPS(bs) + j); 407 if (!idx) { 408 /* 409 * Can happen if memory is low or if we 410 * run out of 32-bit indices. 411 */ 412 rc = block_put(b); 413 return (rc == EOK) ? ENOMEM : rc; 414 } 415 rc = fat_node_get_core(&nodep, idx); 416 fibril_mutex_unlock(&idx->lock); 417 if (rc != EOK) { 418 (void) block_put(b); 419 return rc; 420 } 421 *rfn = FS_NODE(nodep); 422 rc = block_put(b); 423 if (rc != EOK) 424 (void) fat_node_put(*rfn); 406 rc = fat_node_get_core(&nodep, idx); 407 fibril_mutex_unlock(&idx->lock); 408 if (rc != EOK) { 409 (void) fat_directory_close(&di); 425 410 return rc; 426 411 } 427 } 428 rc = block_put(b); 429 if (rc != EOK) 412 *rfn = FS_NODE(nodep); 413 rc = fat_directory_close(&di); 414 if (rc != EOK) 415 (void) fat_node_put(*rfn); 430 416 return rc; 431 } 432 417 } else { 418 rc = fat_directory_next(&di); 419 if (rc != EOK) 420 break; 421 } 422 } 423 (void) fat_directory_close(&di); 433 424 *rfn = NULL; 434 425 return EOK; … … 436 427 437 428 /** Instantiate a FAT in-core node. */ 438 int fat_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)429 int fat_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index) 439 430 { 440 431 fat_node_t *nodep; … … 442 433 int rc; 443 434 444 idxp = fat_idx_get_by_index( devmap_handle, index);435 idxp = fat_idx_get_by_index(service_id, index); 445 436 if (!idxp) { 446 437 *rfn = NULL; … … 473 464 if (nodep->idx) { 474 465 fibril_mutex_lock(&ffn_mutex); 475 list_append(&nodep->ffn_link, &ffn_ head);466 list_append(&nodep->ffn_link, &ffn_list); 476 467 fibril_mutex_unlock(&ffn_mutex); 477 468 } else { … … 493 484 } 494 485 495 int fat_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int flags)486 int fat_create_node(fs_node_t **rfn, service_id_t service_id, int flags) 496 487 { 497 488 fat_idx_t *idxp; … … 501 492 int rc; 502 493 503 bs = block_bb_get( devmap_handle);494 bs = block_bb_get(service_id); 504 495 if (flags & L_DIRECTORY) { 505 496 /* allocate a cluster */ 506 rc = fat_alloc_clusters(bs, devmap_handle, 1, &mcl, &lcl);497 rc = fat_alloc_clusters(bs, service_id, 1, &mcl, &lcl); 507 498 if (rc != EOK) 508 499 return rc; 509 500 /* populate the new cluster with unused dentries */ 510 rc = fat_zero_cluster(bs, devmap_handle, mcl);511 if (rc != EOK) { 512 (void) fat_free_clusters(bs, devmap_handle, mcl);501 rc = fat_zero_cluster(bs, service_id, mcl); 502 if (rc != EOK) { 503 (void) fat_free_clusters(bs, service_id, mcl); 513 504 return rc; 514 505 } … … 517 508 rc = fat_node_get_new(&nodep); 518 509 if (rc != EOK) { 519 (void) fat_free_clusters(bs, devmap_handle, mcl);520 return rc; 521 } 522 rc = fat_idx_get_new(&idxp, devmap_handle);510 (void) fat_free_clusters(bs, service_id, mcl); 511 return rc; 512 } 513 rc = fat_idx_get_new(&idxp, service_id); 523 514 if (rc != EOK) { 524 (void) fat_free_clusters(bs, devmap_handle, mcl);515 (void) fat_free_clusters(bs, service_id, mcl); 525 516 (void) fat_node_put(FS_NODE(nodep)); 526 517 return rc; … … 571 562 assert(!has_children); 572 563 573 bs = block_bb_get(nodep->idx-> devmap_handle);564 bs = block_bb_get(nodep->idx->service_id); 574 565 if (nodep->firstc != FAT_CLST_RES0) { 575 566 assert(nodep->size); 576 567 /* Free all clusters allocated to the node. */ 577 rc = fat_free_clusters(bs, nodep->idx-> devmap_handle,568 rc = fat_free_clusters(bs, nodep->idx->service_id, 578 569 nodep->firstc); 579 570 } … … 592 583 fat_bs_t *bs; 593 584 block_t *b; 594 unsigned i, j; 595 unsigned blocks; 596 fat_cluster_t mcl, lcl; 585 fat_directory_t di; 586 fat_dentry_t de; 597 587 int rc; 598 588 … … 608 598 fibril_mutex_unlock(&childp->lock); 609 599 610 if (!fat_dentry_name_verify(name)) { 611 /* 612 * Attempt to create unsupported name. 613 */ 600 if (!fat_valid_name(name)) 614 601 return ENOTSUP; 615 } 616 617 /* 618 * Get us an unused parent node's dentry or grow the parent and allocate 619 * a new one. 620 */ 621 602 622 603 fibril_mutex_lock(&parentp->idx->lock); 623 bs = block_bb_get(parentp->idx->devmap_handle); 624 625 blocks = parentp->size / BPS(bs); 626 627 for (i = 0; i < blocks; i++) { 628 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 629 if (rc != EOK) { 630 fibril_mutex_unlock(&parentp->idx->lock); 631 return rc; 632 } 633 for (j = 0; j < DPS(bs); j++) { 634 d = ((fat_dentry_t *)b->data) + j; 635 switch (fat_classify_dentry(d)) { 636 case FAT_DENTRY_SKIP: 637 case FAT_DENTRY_VALID: 638 /* skipping used and meta entries */ 639 continue; 640 case FAT_DENTRY_FREE: 641 case FAT_DENTRY_LAST: 642 /* found an empty slot */ 643 goto hit; 644 } 645 } 646 rc = block_put(b); 647 if (rc != EOK) { 648 fibril_mutex_unlock(&parentp->idx->lock); 649 return rc; 650 } 651 } 652 j = 0; 653 654 /* 655 * We need to grow the parent in order to create a new unused dentry. 656 */ 657 if (parentp->firstc == FAT_CLST_ROOT) { 658 /* Can't grow the root directory. */ 659 fibril_mutex_unlock(&parentp->idx->lock); 660 return ENOSPC; 661 } 662 rc = fat_alloc_clusters(bs, parentp->idx->devmap_handle, 1, &mcl, &lcl); 604 bs = block_bb_get(parentp->idx->service_id); 605 rc = fat_directory_open(parentp, &di); 663 606 if (rc != EOK) { 664 607 fibril_mutex_unlock(&parentp->idx->lock); 665 608 return rc; 666 609 } 667 rc = fat_zero_cluster(bs, parentp->idx->devmap_handle, mcl); 668 if (rc != EOK) { 669 (void) fat_free_clusters(bs, parentp->idx->devmap_handle, mcl); 670 fibril_mutex_unlock(&parentp->idx->lock); 671 return rc; 672 } 673 rc = fat_append_clusters(bs, parentp, mcl, lcl); 674 if (rc != EOK) { 675 (void) fat_free_clusters(bs, parentp->idx->devmap_handle, mcl); 676 fibril_mutex_unlock(&parentp->idx->lock); 677 return rc; 678 } 679 parentp->size += BPS(bs) * SPC(bs); 680 parentp->dirty = true; /* need to sync node */ 681 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 682 if (rc != EOK) { 683 fibril_mutex_unlock(&parentp->idx->lock); 684 return rc; 685 } 686 d = (fat_dentry_t *)b->data; 687 688 hit: 610 689 611 /* 690 612 * At this point we only establish the link between the parent and the … … 693 615 * dentry data is kept in the child node structure. 694 616 */ 695 memset(d, 0, sizeof(fat_dentry_t)); 696 fat_dentry_name_set(d, name); 697 b->dirty = true; /* need to sync block */ 698 rc = block_put(b); 617 memset(&de, 0, sizeof(fat_dentry_t)); 618 619 rc = fat_directory_write(&di, name, &de); 620 if (rc != EOK) { 621 (void) fat_directory_close(&di); 622 fibril_mutex_unlock(&parentp->idx->lock); 623 return rc; 624 } 625 rc = fat_directory_close(&di); 626 if (rc != EOK) { 627 fibril_mutex_unlock(&parentp->idx->lock); 628 return rc; 629 } 630 699 631 fibril_mutex_unlock(&parentp->idx->lock); 700 if (rc != EOK)701 return rc;702 632 703 633 fibril_mutex_lock(&childp->idx->lock); 704 634 705 635 if (childp->type == FAT_DIRECTORY) { 706 636 /* … … 721 651 d = (fat_dentry_t *) b->data; 722 652 if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) || 723 ( str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) {653 (bcmp(d->name, FAT_NAME_DOT, FAT_NAME_LEN)) == 0) { 724 654 memset(d, 0, sizeof(fat_dentry_t)); 725 655 memcpy(d->name, FAT_NAME_DOT, FAT_NAME_LEN); … … 731 661 d++; 732 662 if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) || 733 ( str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) {663 (bcmp(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN) == 0)) { 734 664 memset(d, 0, sizeof(fat_dentry_t)); 735 665 memcpy(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN); 736 666 memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN); 737 667 d->attr = FAT_ATTR_SUBDIR; 738 d->firstc = (parentp->firstc == FAT_ CLST_ROOT) ?739 host2uint16_t_le(FAT_CLST_R ES0) :668 d->firstc = (parentp->firstc == FAT_ROOT_CLST(bs)) ? 669 host2uint16_t_le(FAT_CLST_ROOTPAR) : 740 670 host2uint16_t_le(parentp->firstc); 741 671 /* TODO: initialize also the date/time members. */ … … 751 681 752 682 childp->idx->pfc = parentp->firstc; 753 childp->idx->pdi = i * DPS(bs) + j;683 childp->idx->pdi = di.pos; /* di.pos holds absolute position of SFN entry */ 754 684 fibril_mutex_unlock(&childp->idx->lock); 755 685 … … 771 701 fat_node_t *parentp = FAT_NODE(pfn); 772 702 fat_node_t *childp = FAT_NODE(cfn); 773 fat_bs_t *bs;774 fat_dentry_t *d;775 block_t *b;776 703 bool has_children; 777 704 int rc; … … 779 706 if (!parentp) 780 707 return EBUSY; 781 708 782 709 rc = fat_has_children(&has_children, cfn); 783 710 if (rc != EOK) … … 790 717 assert(childp->lnkcnt == 1); 791 718 fibril_mutex_lock(&childp->idx->lock); 792 bs = block_bb_get(childp->idx->devmap_handle); 793 794 rc = _fat_block_get(&b, bs, childp->idx->devmap_handle, childp->idx->pfc, 795 NULL, (childp->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs), 796 BLOCK_FLAGS_NONE); 797 if (rc != EOK) 719 720 fat_directory_t di; 721 rc = fat_directory_open(parentp, &di); 722 if (rc != EOK) 798 723 goto error; 799 d = (fat_dentry_t *)b->data + 800 (childp->idx->pdi % (BPS(bs) / sizeof(fat_dentry_t))); 801 /* mark the dentry as not-currently-used */ 802 d->name[0] = FAT_DENTRY_ERASED; 803 b->dirty = true; /* need to sync block */ 804 rc = block_put(b); 724 rc = fat_directory_seek(&di, childp->idx->pdi); 725 if (rc != EOK) 726 goto error; 727 rc = fat_directory_erase(&di); 728 if (rc != EOK) 729 goto error; 730 rc = fat_directory_close(&di); 805 731 if (rc != EOK) 806 732 goto error; … … 821 747 822 748 error: 823 fibril_mutex_unlock(&parentp->idx->lock); 749 (void) fat_directory_close(&di); 750 fibril_mutex_unlock(&childp->idx->lock); 824 751 fibril_mutex_unlock(&childp->lock); 825 fibril_mutex_unlock(& childp->idx->lock);752 fibril_mutex_unlock(&parentp->lock); 826 753 return rc; 827 754 } … … 840 767 return EOK; 841 768 } 842 769 843 770 fibril_mutex_lock(&nodep->idx->lock); 844 bs = block_bb_get(nodep->idx-> devmap_handle);771 bs = block_bb_get(nodep->idx->service_id); 845 772 846 773 blocks = nodep->size / BPS(bs); … … 848 775 for (i = 0; i < blocks; i++) { 849 776 fat_dentry_t *d; 850 777 851 778 rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE); 852 779 if (rc != EOK) { … … 876 803 if (rc != EOK) { 877 804 fibril_mutex_unlock(&nodep->idx->lock); 878 return rc; 805 return rc; 879 806 } 880 807 } … … 901 828 } 902 829 903 char fat_plb_get_char(unsigned pos)904 {905 return fat_reg.plb_ro[pos % PLB_SIZE];906 }907 908 830 bool fat_is_directory(fs_node_t *fn) 909 831 { … … 916 838 } 917 839 918 devmap_handle_t fat_device_get(fs_node_t *node)840 service_id_t fat_device_get(fs_node_t *node) 919 841 { 920 842 return 0; … … 936 858 .size_get = fat_size_get, 937 859 .lnkcnt_get = fat_lnkcnt_get, 938 .plb_get_char = fat_plb_get_char,939 860 .is_directory = fat_is_directory, 940 861 .is_file = fat_is_file, … … 943 864 944 865 /* 945 * VFSoperations.866 * FAT VFS_OUT operations. 946 867 */ 947 868 948 void fat_mounted(ipc_callid_t rid, ipc_call_t *request) 949 { 950 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 869 static int 870 fat_mounted(service_id_t service_id, const char *opts, fs_index_t *index, 871 aoff64_t *size, unsigned *linkcnt) 872 { 951 873 enum cache_mode cmode; 952 874 fat_bs_t *bs; 953 954 /* Accept the mount options */ 955 char *opts; 956 int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL); 957 958 if (rc != EOK) { 959 async_answer_0(rid, rc); 960 return; 961 } 875 int rc; 962 876 963 877 /* Check for option enabling write through. */ … … 967 881 cmode = CACHE_MODE_WB; 968 882 969 free(opts);970 971 883 /* initialize libblock */ 972 rc = block_init(EXCHANGE_SERIALIZE, devmap_handle, BS_SIZE); 884 rc = block_init(EXCHANGE_SERIALIZE, service_id, BS_SIZE); 885 if (rc != EOK) 886 return rc; 887 888 /* prepare the boot block */ 889 rc = block_bb_read(service_id, BS_BLOCK); 973 890 if (rc != EOK) { 974 async_answer_0(rid, rc); 975 return; 976 } 977 978 /* prepare the boot block */ 979 rc = block_bb_read(devmap_handle, BS_BLOCK); 980 if (rc != EOK) { 981 block_fini(devmap_handle); 982 async_answer_0(rid, rc); 983 return; 891 block_fini(service_id); 892 return rc; 984 893 } 985 894 986 895 /* get the buffer with the boot sector */ 987 bs = block_bb_get( devmap_handle);896 bs = block_bb_get(service_id); 988 897 989 898 if (BPS(bs) != BS_SIZE) { 990 block_fini(devmap_handle); 991 async_answer_0(rid, ENOTSUP); 992 return; 899 block_fini(service_id); 900 return ENOTSUP; 993 901 } 994 902 995 903 /* Initialize the block cache */ 996 rc = block_cache_init( devmap_handle, BPS(bs), 0 /* XXX */, cmode);904 rc = block_cache_init(service_id, BPS(bs), 0 /* XXX */, cmode); 997 905 if (rc != EOK) { 998 block_fini(devmap_handle); 999 async_answer_0(rid, rc); 1000 return; 906 block_fini(service_id); 907 return rc; 1001 908 } 1002 909 1003 910 /* Do some simple sanity checks on the file system. */ 1004 rc = fat_sanity_check(bs, devmap_handle);911 rc = fat_sanity_check(bs, service_id); 1005 912 if (rc != EOK) { 1006 (void) block_cache_fini(devmap_handle); 1007 block_fini(devmap_handle); 1008 async_answer_0(rid, rc); 1009 return; 1010 } 1011 1012 rc = fat_idx_init_by_devmap_handle(devmap_handle); 913 (void) block_cache_fini(service_id); 914 block_fini(service_id); 915 return rc; 916 } 917 918 rc = fat_idx_init_by_service_id(service_id); 1013 919 if (rc != EOK) { 1014 (void) block_cache_fini(devmap_handle); 1015 block_fini(devmap_handle); 1016 async_answer_0(rid, rc); 1017 return; 920 (void) block_cache_fini(service_id); 921 block_fini(service_id); 922 return rc; 1018 923 } 1019 924 … … 1021 926 fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t)); 1022 927 if (!rfn) { 1023 (void) block_cache_fini( devmap_handle);1024 block_fini( devmap_handle);1025 fat_idx_fini_by_ devmap_handle(devmap_handle);1026 async_answer_0(rid, ENOMEM);1027 return;1028 } 928 (void) block_cache_fini(service_id); 929 block_fini(service_id); 930 fat_idx_fini_by_service_id(service_id); 931 return ENOMEM; 932 } 933 1029 934 fs_node_initialize(rfn); 1030 935 fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t)); 1031 936 if (!rootp) { 1032 937 free(rfn); 1033 (void) block_cache_fini(devmap_handle); 1034 block_fini(devmap_handle); 1035 fat_idx_fini_by_devmap_handle(devmap_handle); 1036 async_answer_0(rid, ENOMEM); 1037 return; 938 (void) block_cache_fini(service_id); 939 block_fini(service_id); 940 fat_idx_fini_by_service_id(service_id); 941 return ENOMEM; 1038 942 } 1039 943 fat_node_initialize(rootp); 1040 944 1041 fat_idx_t *ridxp = fat_idx_get_by_pos( devmap_handle, FAT_CLST_ROOTPAR, 0);945 fat_idx_t *ridxp = fat_idx_get_by_pos(service_id, FAT_CLST_ROOTPAR, 0); 1042 946 if (!ridxp) { 1043 947 free(rfn); 1044 948 free(rootp); 1045 (void) block_cache_fini(devmap_handle); 1046 block_fini(devmap_handle); 1047 fat_idx_fini_by_devmap_handle(devmap_handle); 1048 async_answer_0(rid, ENOMEM); 1049 return; 949 (void) block_cache_fini(service_id); 950 block_fini(service_id); 951 fat_idx_fini_by_service_id(service_id); 952 return ENOMEM; 1050 953 } 1051 954 assert(ridxp->index == 0); … … 1053 956 1054 957 rootp->type = FAT_DIRECTORY; 1055 rootp->firstc = FAT_ CLST_ROOT;958 rootp->firstc = FAT_ROOT_CLST(bs); 1056 959 rootp->refcnt = 1; 1057 960 rootp->lnkcnt = 0; /* FS root is not linked */ 1058 rootp->size = RDE(bs) * sizeof(fat_dentry_t); 961 962 if (FAT_IS_FAT32(bs)) { 963 uint32_t clusters; 964 rc = fat_clusters_get(&clusters, bs, service_id, rootp->firstc); 965 if (rc != EOK) { 966 free(rfn); 967 free(rootp); 968 (void) block_cache_fini(service_id); 969 block_fini(service_id); 970 fat_idx_fini_by_service_id(service_id); 971 return ENOTSUP; 972 } 973 rootp->size = BPS(bs) * SPC(bs) * clusters; 974 } else 975 rootp->size = RDE(bs) * sizeof(fat_dentry_t); 976 1059 977 rootp->idx = ridxp; 1060 978 ridxp->nodep = rootp; 1061 979 rootp->bp = rfn; 1062 980 rfn->data = rootp; 1063 981 1064 982 fibril_mutex_unlock(&ridxp->lock); 1065 983 1066 async_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt); 1067 } 1068 1069 void fat_mount(ipc_callid_t rid, ipc_call_t *request) 1070 { 1071 libfs_mount(&fat_libfs_ops, fat_reg.fs_handle, rid, request); 1072 } 1073 1074 void fat_unmounted(ipc_callid_t rid, ipc_call_t *request) 1075 { 1076 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 984 *index = ridxp->index; 985 *size = rootp->size; 986 *linkcnt = rootp->lnkcnt; 987 988 return EOK; 989 } 990 991 static int fat_unmounted(service_id_t service_id) 992 { 1077 993 fs_node_t *fn; 1078 994 fat_node_t *nodep; 1079 995 int rc; 1080 996 1081 rc = fat_root_get(&fn, devmap_handle); 1082 if (rc != EOK) { 1083 async_answer_0(rid, rc); 1084 return; 1085 } 997 rc = fat_root_get(&fn, service_id); 998 if (rc != EOK) 999 return rc; 1086 1000 nodep = FAT_NODE(fn); 1087 1001 … … 1092 1006 if (nodep->refcnt != 2) { 1093 1007 (void) fat_node_put(fn); 1094 async_answer_0(rid, EBUSY); 1095 return; 1096 } 1097 1008 return EBUSY; 1009 } 1010 1098 1011 /* 1099 1012 * Put the root node and force it to the FAT free node list. … … 1107 1020 * stop using libblock for this instance. 1108 1021 */ 1109 (void) fat_node_fini_by_devmap_handle(devmap_handle); 1110 fat_idx_fini_by_devmap_handle(devmap_handle); 1111 (void) block_cache_fini(devmap_handle); 1112 block_fini(devmap_handle); 1113 1114 async_answer_0(rid, EOK); 1115 } 1116 1117 void fat_unmount(ipc_callid_t rid, ipc_call_t *request) 1118 { 1119 libfs_unmount(&fat_libfs_ops, rid, request); 1120 } 1121 1122 void fat_lookup(ipc_callid_t rid, ipc_call_t *request) 1123 { 1124 libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request); 1125 } 1126 1127 void fat_read(ipc_callid_t rid, ipc_call_t *request) 1128 { 1129 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 1130 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 1131 aoff64_t pos = 1132 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request)); 1022 (void) fat_node_fini_by_service_id(service_id); 1023 fat_idx_fini_by_service_id(service_id); 1024 (void) block_cache_fini(service_id); 1025 block_fini(service_id); 1026 1027 return EOK; 1028 } 1029 1030 static int 1031 fat_read(service_id_t service_id, fs_index_t index, aoff64_t pos, 1032 size_t *rbytes) 1033 { 1133 1034 fs_node_t *fn; 1134 1035 fat_node_t *nodep; … … 1138 1039 int rc; 1139 1040 1140 rc = fat_node_get(&fn, devmap_handle, index); 1141 if (rc != EOK) { 1142 async_answer_0(rid, rc); 1143 return; 1144 } 1145 if (!fn) { 1146 async_answer_0(rid, ENOENT); 1147 return; 1148 } 1041 rc = fat_node_get(&fn, service_id, index); 1042 if (rc != EOK) 1043 return rc; 1044 if (!fn) 1045 return ENOENT; 1149 1046 nodep = FAT_NODE(fn); 1150 1047 … … 1154 1051 fat_node_put(fn); 1155 1052 async_answer_0(callid, EINVAL); 1156 async_answer_0(rid, EINVAL); 1157 return; 1158 } 1159 1160 bs = block_bb_get(devmap_handle); 1053 return EINVAL; 1054 } 1055 1056 bs = block_bb_get(service_id); 1161 1057 1162 1058 if (nodep->type == FAT_FILE) { … … 1178 1074 fat_node_put(fn); 1179 1075 async_answer_0(callid, rc); 1180 async_answer_0(rid, rc); 1181 return; 1076 return rc; 1182 1077 } 1183 1078 (void) async_data_read_finalize(callid, … … 1186 1081 if (rc != EOK) { 1187 1082 fat_node_put(fn); 1188 async_answer_0(rid, rc); 1189 return; 1083 return rc; 1190 1084 } 1191 1085 } 1192 1086 } else { 1193 unsigned bnum;1194 1087 aoff64_t spos = pos; 1195 char name[FAT_ NAME_LEN + 1 + FAT_EXT_LEN + 1];1088 char name[FAT_LFN_NAME_SIZE]; 1196 1089 fat_dentry_t *d; 1197 1090 … … 1200 1093 assert(BPS(bs) % sizeof(fat_dentry_t) == 0); 1201 1094 1202 /* 1203 * Our strategy for readdir() is to use the position pointer as 1204 * an index into the array of all dentries. On entry, it points 1205 * to the first unread dentry. If we skip any dentries, we bump 1206 * the position pointer accordingly. 1207 */ 1208 bnum = (pos * sizeof(fat_dentry_t)) / BPS(bs); 1209 while (bnum < nodep->size / BPS(bs)) { 1210 aoff64_t o; 1211 1212 rc = fat_block_get(&b, bs, nodep, bnum, 1213 BLOCK_FLAGS_NONE); 1214 if (rc != EOK) 1215 goto err; 1216 for (o = pos % (BPS(bs) / sizeof(fat_dentry_t)); 1217 o < BPS(bs) / sizeof(fat_dentry_t); 1218 o++, pos++) { 1219 d = ((fat_dentry_t *)b->data) + o; 1220 switch (fat_classify_dentry(d)) { 1221 case FAT_DENTRY_SKIP: 1222 case FAT_DENTRY_FREE: 1223 continue; 1224 case FAT_DENTRY_LAST: 1225 rc = block_put(b); 1226 if (rc != EOK) 1227 goto err; 1228 goto miss; 1229 default: 1230 case FAT_DENTRY_VALID: 1231 fat_dentry_name_get(d, name); 1232 rc = block_put(b); 1233 if (rc != EOK) 1234 goto err; 1235 goto hit; 1236 } 1237 } 1238 rc = block_put(b); 1239 if (rc != EOK) 1240 goto err; 1241 bnum++; 1242 } 1243 miss: 1244 rc = fat_node_put(fn); 1245 async_answer_0(callid, rc != EOK ? rc : ENOENT); 1246 async_answer_1(rid, rc != EOK ? rc : ENOENT, 0); 1247 return; 1095 fat_directory_t di; 1096 rc = fat_directory_open(nodep, &di); 1097 if (rc != EOK) 1098 goto err; 1099 rc = fat_directory_seek(&di, pos); 1100 if (rc != EOK) { 1101 (void) fat_directory_close(&di); 1102 goto err; 1103 } 1104 1105 rc = fat_directory_read(&di, name, &d); 1106 if (rc == EOK) 1107 goto hit; 1108 if (rc == ENOENT) 1109 goto miss; 1248 1110 1249 1111 err: 1250 1112 (void) fat_node_put(fn); 1251 1113 async_answer_0(callid, rc); 1252 async_answer_0(rid, rc); 1253 return; 1114 return rc; 1115 1116 miss: 1117 rc = fat_directory_close(&di); 1118 if (rc != EOK) 1119 goto err; 1120 rc = fat_node_put(fn); 1121 async_answer_0(callid, rc != EOK ? rc : ENOENT); 1122 *rbytes = 0; 1123 return rc != EOK ? rc : ENOENT; 1254 1124 1255 1125 hit: 1256 (void) async_data_read_finalize(callid, name, str_size(name) + 1); 1126 pos = di.pos; 1127 rc = fat_directory_close(&di); 1128 if (rc != EOK) 1129 goto err; 1130 (void) async_data_read_finalize(callid, name, 1131 str_size(name) + 1); 1257 1132 bytes = (pos - spos) + 1; 1258 1133 } 1259 1134 1260 1135 rc = fat_node_put(fn); 1261 async_answer_1(rid, rc, (sysarg_t)bytes); 1262 } 1263 1264 void fat_write(ipc_callid_t rid, ipc_call_t *request) 1265 { 1266 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 1267 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 1268 aoff64_t pos = 1269 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request)); 1136 *rbytes = bytes; 1137 return rc; 1138 } 1139 1140 static int 1141 fat_write(service_id_t service_id, fs_index_t index, aoff64_t pos, 1142 size_t *wbytes, aoff64_t *nsize) 1143 { 1270 1144 fs_node_t *fn; 1271 1145 fat_node_t *nodep; 1272 1146 fat_bs_t *bs; 1273 size_t bytes , size;1147 size_t bytes; 1274 1148 block_t *b; 1275 1149 aoff64_t boundary; … … 1277 1151 int rc; 1278 1152 1279 rc = fat_node_get(&fn, devmap_handle, index); 1280 if (rc != EOK) { 1281 async_answer_0(rid, rc); 1282 return; 1283 } 1284 if (!fn) { 1285 async_answer_0(rid, ENOENT); 1286 return; 1287 } 1153 rc = fat_node_get(&fn, service_id, index); 1154 if (rc != EOK) 1155 return rc; 1156 if (!fn) 1157 return ENOENT; 1288 1158 nodep = FAT_NODE(fn); 1289 1159 1290 1160 ipc_callid_t callid; 1291 1161 size_t len; … … 1293 1163 (void) fat_node_put(fn); 1294 1164 async_answer_0(callid, EINVAL); 1295 async_answer_0(rid, EINVAL); 1296 return; 1297 } 1298 1299 bs = block_bb_get(devmap_handle); 1165 return EINVAL; 1166 } 1167 1168 bs = block_bb_get(service_id); 1300 1169 1301 1170 /* … … 1304 1173 * but this one greatly simplifies fat_write(). Note that we can afford 1305 1174 * to do this because the client must be ready to handle the return 1306 * value signalizing a smaller number of bytes written. 1307 */ 1175 * value signalizing a smaller number of bytes written. 1176 */ 1308 1177 bytes = min(len, BPS(bs) - pos % BPS(bs)); 1309 1178 if (bytes == BPS(bs)) 1310 1179 flags |= BLOCK_FLAGS_NOREAD; 1311 1180 1312 1181 boundary = ROUND_UP(nodep->size, BPC(bs)); 1313 1182 if (pos < boundary) { … … 1322 1191 (void) fat_node_put(fn); 1323 1192 async_answer_0(callid, rc); 1324 async_answer_0(rid, rc); 1325 return; 1193 return rc; 1326 1194 } 1327 1195 rc = fat_block_get(&b, bs, nodep, pos / BPS(bs), flags); … … 1329 1197 (void) fat_node_put(fn); 1330 1198 async_answer_0(callid, rc); 1331 async_answer_0(rid, rc); 1332 return; 1199 return rc; 1333 1200 } 1334 1201 (void) async_data_write_finalize(callid, … … 1338 1205 if (rc != EOK) { 1339 1206 (void) fat_node_put(fn); 1340 async_answer_0(rid, rc); 1341 return; 1207 return rc; 1342 1208 } 1343 1209 if (pos + bytes > nodep->size) { … … 1345 1211 nodep->dirty = true; /* need to sync node */ 1346 1212 } 1347 size = nodep->size; 1213 *wbytes = bytes; 1214 *nsize = nodep->size; 1348 1215 rc = fat_node_put(fn); 1349 async_answer_2(rid, rc, bytes, nodep->size); 1350 return; 1216 return rc; 1351 1217 } else { 1352 1218 /* … … 1355 1221 */ 1356 1222 unsigned nclsts; 1357 fat_cluster_t mcl, lcl; 1358 1223 fat_cluster_t mcl, lcl; 1224 1359 1225 nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs); 1360 1226 /* create an independent chain of nclsts clusters in all FATs */ 1361 rc = fat_alloc_clusters(bs, devmap_handle, nclsts, &mcl, &lcl);1227 rc = fat_alloc_clusters(bs, service_id, nclsts, &mcl, &lcl); 1362 1228 if (rc != EOK) { 1363 1229 /* could not allocate a chain of nclsts clusters */ 1364 1230 (void) fat_node_put(fn); 1365 1231 async_answer_0(callid, rc); 1366 async_answer_0(rid, rc); 1367 return; 1232 return rc; 1368 1233 } 1369 1234 /* zero fill any gaps */ 1370 1235 rc = fat_fill_gap(bs, nodep, mcl, pos); 1371 1236 if (rc != EOK) { 1372 (void) fat_free_clusters(bs, devmap_handle, mcl);1237 (void) fat_free_clusters(bs, service_id, mcl); 1373 1238 (void) fat_node_put(fn); 1374 1239 async_answer_0(callid, rc); 1375 async_answer_0(rid, rc); 1376 return; 1377 } 1378 rc = _fat_block_get(&b, bs, devmap_handle, lcl, NULL, 1240 return rc; 1241 } 1242 rc = _fat_block_get(&b, bs, service_id, lcl, NULL, 1379 1243 (pos / BPS(bs)) % SPC(bs), flags); 1380 1244 if (rc != EOK) { 1381 (void) fat_free_clusters(bs, devmap_handle, mcl);1245 (void) fat_free_clusters(bs, service_id, mcl); 1382 1246 (void) fat_node_put(fn); 1383 1247 async_answer_0(callid, rc); 1384 async_answer_0(rid, rc); 1385 return; 1248 return rc; 1386 1249 } 1387 1250 (void) async_data_write_finalize(callid, … … 1390 1253 rc = block_put(b); 1391 1254 if (rc != EOK) { 1392 (void) fat_free_clusters(bs, devmap_handle, mcl);1255 (void) fat_free_clusters(bs, service_id, mcl); 1393 1256 (void) fat_node_put(fn); 1394 async_answer_0(rid, rc); 1395 return; 1257 return rc; 1396 1258 } 1397 1259 /* … … 1401 1263 rc = fat_append_clusters(bs, nodep, mcl, lcl); 1402 1264 if (rc != EOK) { 1403 (void) fat_free_clusters(bs, devmap_handle, mcl);1265 (void) fat_free_clusters(bs, service_id, mcl); 1404 1266 (void) fat_node_put(fn); 1405 async_answer_0(rid, rc);1406 return;1407 }1408 nodep->size = size = pos + bytes;1267 return rc; 1268 } 1269 *nsize = nodep->size = pos + bytes; 1270 rc = fat_node_put(fn); 1409 1271 nodep->dirty = true; /* need to sync node */ 1410 rc = fat_node_put(fn); 1411 async_answer_2(rid, rc, bytes, size); 1412 return; 1413 } 1414 } 1415 1416 void fat_truncate(ipc_callid_t rid, ipc_call_t *request) 1417 { 1418 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 1419 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 1420 aoff64_t size = 1421 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request)); 1272 *wbytes = bytes; 1273 return rc; 1274 } 1275 } 1276 1277 static int 1278 fat_truncate(service_id_t service_id, fs_index_t index, aoff64_t size) 1279 { 1422 1280 fs_node_t *fn; 1423 1281 fat_node_t *nodep; … … 1425 1283 int rc; 1426 1284 1427 rc = fat_node_get(&fn, devmap_handle, index); 1428 if (rc != EOK) { 1429 async_answer_0(rid, rc); 1430 return; 1431 } 1432 if (!fn) { 1433 async_answer_0(rid, ENOENT); 1434 return; 1435 } 1285 rc = fat_node_get(&fn, service_id, index); 1286 if (rc != EOK) 1287 return rc; 1288 if (!fn) 1289 return ENOENT; 1436 1290 nodep = FAT_NODE(fn); 1437 1291 1438 bs = block_bb_get( devmap_handle);1292 bs = block_bb_get(service_id); 1439 1293 1440 1294 if (nodep->size == size) { … … 1452 1306 nodep->size = size; 1453 1307 nodep->dirty = true; /* need to sync node */ 1454 rc = EOK; 1308 rc = EOK; 1455 1309 } else { 1456 1310 /* … … 1463 1317 } else { 1464 1318 fat_cluster_t lastc; 1465 rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc,1319 rc = fat_cluster_walk(bs, service_id, nodep->firstc, 1466 1320 &lastc, NULL, (size - 1) / BPC(bs)); 1467 1321 if (rc != EOK) … … 1473 1327 nodep->size = size; 1474 1328 nodep->dirty = true; /* need to sync node */ 1475 rc = EOK; 1329 rc = EOK; 1476 1330 } 1477 1331 out: 1478 1332 fat_node_put(fn); 1479 async_answer_0(rid, rc); 1480 return; 1481 } 1482 1483 void fat_close(ipc_callid_t rid, ipc_call_t *request) 1484 { 1485 async_answer_0(rid, EOK); 1486 } 1487 1488 void fat_destroy(ipc_callid_t rid, ipc_call_t *request) 1489 { 1490 devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request); 1491 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1333 return rc; 1334 } 1335 1336 static int fat_close(service_id_t service_id, fs_index_t index) 1337 { 1338 return EOK; 1339 } 1340 1341 static int fat_destroy(service_id_t service_id, fs_index_t index) 1342 { 1492 1343 fs_node_t *fn; 1493 1344 fat_node_t *nodep; 1494 1345 int rc; 1495 1346 1496 rc = fat_node_get(&fn, devmap_handle, index); 1497 if (rc != EOK) { 1498 async_answer_0(rid, rc); 1499 return; 1500 } 1501 if (!fn) { 1502 async_answer_0(rid, ENOENT); 1503 return; 1504 } 1347 rc = fat_node_get(&fn, service_id, index); 1348 if (rc != EOK) 1349 return rc; 1350 if (!fn) 1351 return ENOENT; 1505 1352 1506 1353 nodep = FAT_NODE(fn); … … 1512 1359 1513 1360 rc = fat_destroy_node(fn); 1514 async_answer_0(rid, rc); 1515 } 1516 1517 void fat_open_node(ipc_callid_t rid, ipc_call_t *request) 1518 { 1519 libfs_open_node(&fat_libfs_ops, fat_reg.fs_handle, rid, request); 1520 } 1521 1522 void fat_stat(ipc_callid_t rid, ipc_call_t *request) 1523 { 1524 libfs_stat(&fat_libfs_ops, fat_reg.fs_handle, rid, request); 1525 } 1526 1527 void fat_sync(ipc_callid_t rid, ipc_call_t *request) 1528 { 1529 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 1530 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 1531 1361 return rc; 1362 } 1363 1364 static int fat_sync(service_id_t service_id, fs_index_t index) 1365 { 1532 1366 fs_node_t *fn; 1533 int rc = fat_node_get(&fn, devmap_handle, index); 1534 if (rc != EOK) { 1535 async_answer_0(rid, rc); 1536 return; 1537 } 1538 if (!fn) { 1539 async_answer_0(rid, ENOENT); 1540 return; 1541 } 1542 1367 int rc = fat_node_get(&fn, service_id, index); 1368 if (rc != EOK) 1369 return rc; 1370 if (!fn) 1371 return ENOENT; 1372 1543 1373 fat_node_t *nodep = FAT_NODE(fn); 1544 1374 1545 1375 nodep->dirty = true; 1546 1376 rc = fat_node_sync(nodep); 1547 1377 1548 1378 fat_node_put(fn); 1549 async_answer_0(rid, rc); 1550 } 1379 return rc; 1380 } 1381 1382 vfs_out_ops_t fat_ops = { 1383 .mounted = fat_mounted, 1384 .unmounted = fat_unmounted, 1385 .read = fat_read, 1386 .write = fat_write, 1387 .truncate = fat_truncate, 1388 .close = fat_close, 1389 .destroy = fat_destroy, 1390 .sync = fat_sync, 1391 }; 1551 1392 1552 1393 /** -
uspace/srv/fs/locfs/Makefile
rd2c67e7 r8ff0bd2 31 31 LIBS = $(LIBFS_PREFIX)/libfs.a 32 32 EXTRA_CFLAGS += -I$(LIBFS_PREFIX) 33 BINARY = devfs33 BINARY = locfs 34 34 STATIC_NEEDED = y 35 35 36 36 SOURCES = \ 37 devfs.c \38 devfs_ops.c37 locfs.c \ 38 locfs_ops.c 39 39 40 40 include $(USPACE_PREFIX)/Makefile.common -
uspace/srv/fs/locfs/locfs.c
rd2c67e7 r8ff0bd2 32 32 33 33 /** 34 * @file devfs.c35 * @brief Devicesfile system.34 * @file locfs.c 35 * @brief Location-service file system. 36 36 * 37 * Every device registered to device mapperis represented as a file in this37 * Every service registered with location service is represented as a file in this 38 38 * file system. 39 39 */ … … 46 46 #include <task.h> 47 47 #include <libfs.h> 48 #include " devfs.h"49 #include " devfs_ops.h"48 #include "locfs.h" 49 #include "locfs_ops.h" 50 50 51 #define NAME " devfs"51 #define NAME "locfs" 52 52 53 static vfs_info_t devfs_vfs_info = {53 static vfs_info_t locfs_vfs_info = { 54 54 .name = NAME, 55 55 .concurrent_read_write = false, … … 57 57 }; 58 58 59 fs_reg_t devfs_reg;60 61 static void devfs_connection(ipc_callid_t iid, ipc_call_t *icall)62 {63 if (iid)64 async_answer_0(iid, EOK);65 66 while (true) {67 ipc_call_t call;68 ipc_callid_t callid = async_get_call(&call);69 70 if (!IPC_GET_IMETHOD(call))71 return;72 73 switch (IPC_GET_IMETHOD(call)) {74 case VFS_OUT_MOUNTED:75 devfs_mounted(callid, &call);76 break;77 case VFS_OUT_MOUNT:78 devfs_mount(callid, &call);79 break;80 case VFS_OUT_UNMOUNTED:81 devfs_unmounted(callid, &call);82 break;83 case VFS_OUT_UNMOUNT:84 devfs_unmount(callid, &call);85 break;86 case VFS_OUT_LOOKUP:87 devfs_lookup(callid, &call);88 break;89 case VFS_OUT_OPEN_NODE:90 devfs_open_node(callid, &call);91 break;92 case VFS_OUT_STAT:93 devfs_stat(callid, &call);94 break;95 case VFS_OUT_READ:96 devfs_read(callid, &call);97 break;98 case VFS_OUT_WRITE:99 devfs_write(callid, &call);100 break;101 case VFS_OUT_TRUNCATE:102 devfs_truncate(callid, &call);103 break;104 case VFS_OUT_CLOSE:105 devfs_close(callid, &call);106 break;107 case VFS_OUT_SYNC:108 devfs_sync(callid, &call);109 break;110 case VFS_OUT_DESTROY:111 devfs_destroy(callid, &call);112 break;113 default:114 async_answer_0(callid, ENOTSUP);115 break;116 }117 }118 }119 120 59 int main(int argc, char *argv[]) 121 60 { 122 61 printf("%s: HelenOS Device Filesystem\n", NAME); 123 62 124 if (! devfs_init()) {125 printf("%s: failed to initialize devfs\n", NAME);63 if (!locfs_init()) { 64 printf("%s: failed to initialize locfs\n", NAME); 126 65 return -1; 127 66 } … … 134 73 } 135 74 136 int rc = fs_register(vfs_sess, & devfs_reg, &devfs_vfs_info,137 devfs_connection);75 int rc = fs_register(vfs_sess, &locfs_vfs_info, &locfs_ops, 76 &locfs_libfs_ops); 138 77 if (rc != EOK) { 139 78 printf("%s: Failed to register file system (%d)\n", NAME, rc); … … 152 91 * @} 153 92 */ 93 -
uspace/srv/fs/locfs/locfs_ops.h
rd2c67e7 r8ff0bd2 29 29 /** @addtogroup fs 30 30 * @{ 31 */ 31 */ 32 32 33 #ifndef DEVFS_DEVFS_H_34 #define DEVFS_DEVFS_H_33 #ifndef LOCFS_LOCFS_OPS_H_ 34 #define LOCFS_LOCFS_OPS_H_ 35 35 36 #include < libfs.h>36 #include <bool.h> 37 37 38 extern fs_reg_t devfs_reg;38 extern bool locfs_init(void); 39 39 40 40 #endif -
uspace/srv/fs/tmpfs/tmpfs.c
rd2c67e7 r8ff0bd2 61 61 }; 62 62 63 fs_reg_t tmpfs_reg;64 65 /**66 * This connection fibril processes VFS requests from VFS.67 *68 * In order to support simultaneous VFS requests, our design is as follows.69 * The connection fibril accepts VFS requests from VFS. If there is only one70 * instance of the fibril, VFS will need to serialize all VFS requests it sends71 * to FAT. To overcome this bottleneck, VFS can send TMPFS the72 * IPC_M_CONNECT_ME_TO call. In that case, a new connection fibril will be73 * created, which in turn will accept the call. Thus, a new phone will be74 * opened for VFS.75 *76 * There are few issues with this arrangement. First, VFS can run out of77 * available phones. In that case, VFS can close some other phones or use one78 * phone for more serialized requests. Similarily, TMPFS can refuse to duplicate79 * the connection. VFS should then just make use of already existing phones and80 * route its requests through them. To avoid paying the fibril creation price81 * upon each request, TMPFS might want to keep the connections open after the82 * request has been completed.83 */84 static void tmpfs_connection(ipc_callid_t iid, ipc_call_t *icall)85 {86 if (iid) {87 /*88 * This only happens for connections opened by89 * IPC_M_CONNECT_ME_TO calls as opposed to callback connections90 * created by IPC_M_CONNECT_TO_ME.91 */92 async_answer_0(iid, EOK);93 }94 95 dprintf(NAME ": connection opened\n");96 97 while (true) {98 ipc_call_t call;99 ipc_callid_t callid = async_get_call(&call);100 101 if (!IPC_GET_IMETHOD(call))102 return;103 104 switch (IPC_GET_IMETHOD(call)) {105 case VFS_OUT_MOUNTED:106 tmpfs_mounted(callid, &call);107 break;108 case VFS_OUT_MOUNT:109 tmpfs_mount(callid, &call);110 break;111 case VFS_OUT_UNMOUNTED:112 tmpfs_unmounted(callid, &call);113 break;114 case VFS_OUT_UNMOUNT:115 tmpfs_unmount(callid, &call);116 break;117 case VFS_OUT_LOOKUP:118 tmpfs_lookup(callid, &call);119 break;120 case VFS_OUT_READ:121 tmpfs_read(callid, &call);122 break;123 case VFS_OUT_WRITE:124 tmpfs_write(callid, &call);125 break;126 case VFS_OUT_TRUNCATE:127 tmpfs_truncate(callid, &call);128 break;129 case VFS_OUT_CLOSE:130 tmpfs_close(callid, &call);131 break;132 case VFS_OUT_DESTROY:133 tmpfs_destroy(callid, &call);134 break;135 case VFS_OUT_OPEN_NODE:136 tmpfs_open_node(callid, &call);137 break;138 case VFS_OUT_STAT:139 tmpfs_stat(callid, &call);140 break;141 case VFS_OUT_SYNC:142 tmpfs_sync(callid, &call);143 break;144 default:145 async_answer_0(callid, ENOTSUP);146 break;147 }148 }149 }150 151 63 int main(int argc, char **argv) 152 64 { … … 165 77 } 166 78 167 int rc = fs_register(vfs_sess, &tmpfs_ reg, &tmpfs_vfs_info,168 tmpfs_connection);79 int rc = fs_register(vfs_sess, &tmpfs_vfs_info, &tmpfs_ops, 80 &tmpfs_libfs_ops); 169 81 if (rc != EOK) { 170 82 printf(NAME ": Failed to register file system (%d)\n", rc); -
uspace/srv/fs/tmpfs/tmpfs.h
rd2c67e7 r8ff0bd2 61 61 fs_node_t *bp; /**< Back pointer to the FS node. */ 62 62 fs_index_t index; /**< TMPFS node index. */ 63 devmap_handle_t devmap_handle;/**< Device handle. */63 service_id_t service_id;/**< Service ID of block device. */ 64 64 link_t nh_link; /**< Nodes hash table link. */ 65 65 tmpfs_dentry_type_t type; … … 67 67 size_t size; /**< File size if type is TMPFS_FILE. */ 68 68 void *data; /**< File content's if type is TMPFS_FILE. */ 69 li nk_t cs_head; /**< Head of child's siblings list. */69 list_t cs_list; /**< Child's siblings list. */ 70 70 } tmpfs_node_t; 71 71 72 extern fs_reg_t tmpfs_reg; 73 72 extern vfs_out_ops_t tmpfs_ops; 74 73 extern libfs_ops_t tmpfs_libfs_ops; 75 74 76 75 extern bool tmpfs_init(void); 77 78 extern void tmpfs_mounted(ipc_callid_t, ipc_call_t *); 79 extern void tmpfs_mount(ipc_callid_t, ipc_call_t *); 80 extern void tmpfs_unmounted(ipc_callid_t, ipc_call_t *); 81 extern void tmpfs_unmount(ipc_callid_t, ipc_call_t *); 82 extern void tmpfs_lookup(ipc_callid_t, ipc_call_t *); 83 extern void tmpfs_read(ipc_callid_t, ipc_call_t *); 84 extern void tmpfs_write(ipc_callid_t, ipc_call_t *); 85 extern void tmpfs_truncate(ipc_callid_t, ipc_call_t *); 86 extern void tmpfs_stat(ipc_callid_t, ipc_call_t *); 87 extern void tmpfs_close(ipc_callid_t, ipc_call_t *); 88 extern void tmpfs_destroy(ipc_callid_t, ipc_call_t *); 89 extern void tmpfs_open_node(ipc_callid_t, ipc_call_t *); 90 extern void tmpfs_sync(ipc_callid_t, ipc_call_t *); 91 92 extern bool tmpfs_restore(devmap_handle_t); 76 extern bool tmpfs_restore(service_id_t); 93 77 94 78 #endif -
uspace/srv/fs/tmpfs/tmpfs_dump.c
rd2c67e7 r8ff0bd2 55 55 56 56 static bool 57 tmpfs_restore_recursion( devmap_handle_t dev, size_t *bufpos, size_t *buflen,57 tmpfs_restore_recursion(service_id_t dsid, size_t *bufpos, size_t *buflen, 58 58 aoff64_t *pos, fs_node_t *pfn) 59 59 { … … 68 68 uint32_t size; 69 69 70 if (block_seqread(d ev, bufpos, buflen, pos, &entry,70 if (block_seqread(dsid, bufpos, buflen, pos, &entry, 71 71 sizeof(entry)) != EOK) 72 72 return false; … … 82 82 return false; 83 83 84 rc = ops->create(&fn, d ev, L_FILE);84 rc = ops->create(&fn, dsid, L_FILE); 85 85 if (rc != EOK || fn == NULL) { 86 86 free(fname); … … 88 88 } 89 89 90 if (block_seqread(d ev, bufpos, buflen, pos, fname,90 if (block_seqread(dsid, bufpos, buflen, pos, fname, 91 91 entry.len) != EOK) { 92 92 (void) ops->destroy(fn); … … 104 104 free(fname); 105 105 106 if (block_seqread(d ev, bufpos, buflen, pos, &size,106 if (block_seqread(dsid, bufpos, buflen, pos, &size, 107 107 sizeof(size)) != EOK) 108 108 return false; … … 116 116 117 117 nodep->size = size; 118 if (block_seqread(d ev, bufpos, buflen, pos, nodep->data,118 if (block_seqread(dsid, bufpos, buflen, pos, nodep->data, 119 119 size) != EOK) 120 120 return false; … … 126 126 return false; 127 127 128 rc = ops->create(&fn, d ev, L_DIRECTORY);128 rc = ops->create(&fn, dsid, L_DIRECTORY); 129 129 if (rc != EOK || fn == NULL) { 130 130 free(fname); … … 132 132 } 133 133 134 if (block_seqread(d ev, bufpos, buflen, pos, fname,134 if (block_seqread(dsid, bufpos, buflen, pos, fname, 135 135 entry.len) != EOK) { 136 136 (void) ops->destroy(fn); … … 148 148 free(fname); 149 149 150 if (!tmpfs_restore_recursion(d ev, bufpos, buflen, pos,150 if (!tmpfs_restore_recursion(dsid, bufpos, buflen, pos, 151 151 fn)) 152 152 return false; … … 161 161 } 162 162 163 bool tmpfs_restore( devmap_handle_t dev)163 bool tmpfs_restore(service_id_t dsid) 164 164 { 165 165 libfs_ops_t *ops = &tmpfs_libfs_ops; … … 167 167 int rc; 168 168 169 rc = block_init(EXCHANGE_SERIALIZE, d ev, TMPFS_COMM_SIZE);169 rc = block_init(EXCHANGE_SERIALIZE, dsid, TMPFS_COMM_SIZE); 170 170 if (rc != EOK) 171 171 return false; … … 176 176 177 177 char tag[6]; 178 if (block_seqread(d ev, &bufpos, &buflen, &pos, tag, 5) != EOK)178 if (block_seqread(dsid, &bufpos, &buflen, &pos, tag, 5) != EOK) 179 179 goto error; 180 180 … … 183 183 goto error; 184 184 185 rc = ops->root_get(&fn, d ev);185 rc = ops->root_get(&fn, dsid); 186 186 if (rc != EOK) 187 187 goto error; 188 188 189 if (!tmpfs_restore_recursion(d ev, &bufpos, &buflen, &pos, fn))190 goto error; 191 192 block_fini(d ev);189 if (!tmpfs_restore_recursion(dsid, &bufpos, &buflen, &pos, fn)) 190 goto error; 191 192 block_fini(dsid); 193 193 return true; 194 194 195 195 error: 196 block_fini(d ev);196 block_fini(dsid); 197 197 return false; 198 198 } -
uspace/srv/fs/tmpfs/tmpfs_ops.c
rd2c67e7 r8ff0bd2 69 69 /* Forward declarations of static functions. */ 70 70 static int tmpfs_match(fs_node_t **, fs_node_t *, const char *); 71 static int tmpfs_node_get(fs_node_t **, devmap_handle_t, fs_index_t);71 static int tmpfs_node_get(fs_node_t **, service_id_t, fs_index_t); 72 72 static int tmpfs_node_open(fs_node_t *); 73 73 static int tmpfs_node_put(fs_node_t *); 74 static int tmpfs_create_node(fs_node_t **, devmap_handle_t, int);74 static int tmpfs_create_node(fs_node_t **, service_id_t, int); 75 75 static int tmpfs_destroy_node(fs_node_t *); 76 76 static int tmpfs_link_node(fs_node_t *, fs_node_t *, const char *); … … 78 78 79 79 /* Implementation of helper functions. */ 80 static int tmpfs_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)81 { 82 return tmpfs_node_get(rfn, devmap_handle, TMPFS_SOME_ROOT);80 static int tmpfs_root_get(fs_node_t **rfn, service_id_t service_id) 81 { 82 return tmpfs_node_get(rfn, service_id, TMPFS_SOME_ROOT); 83 83 } 84 84 85 85 static int tmpfs_has_children(bool *has_children, fs_node_t *fn) 86 86 { 87 *has_children = !list_empty(&TMPFS_NODE(fn)->cs_ head);87 *has_children = !list_empty(&TMPFS_NODE(fn)->cs_list); 88 88 return EOK; 89 89 } … … 104 104 } 105 105 106 static char tmpfs_plb_get_char(unsigned pos)107 {108 return tmpfs_reg.plb_ro[pos % PLB_SIZE];109 }110 111 106 static bool tmpfs_is_directory(fs_node_t *fn) 112 107 { … … 119 114 } 120 115 121 static devmap_handle_t tmpfs_device_get(fs_node_t *fn)116 static service_id_t tmpfs_device_get(fs_node_t *fn) 122 117 { 123 118 return 0; … … 139 134 .size_get = tmpfs_size_get, 140 135 .lnkcnt_get = tmpfs_lnkcnt_get, 141 .plb_get_char = tmpfs_plb_get_char,142 136 .is_directory = tmpfs_is_directory, 143 137 .is_file = tmpfs_is_file, … … 164 158 switch (keys) { 165 159 case 1: 166 return (nodep-> devmap_handle== key[NODES_KEY_DEV]);160 return (nodep->service_id == key[NODES_KEY_DEV]); 167 161 case 2: 168 return ((nodep-> devmap_handle== key[NODES_KEY_DEV]) &&162 return ((nodep->service_id == key[NODES_KEY_DEV]) && 169 163 (nodep->index == key[NODES_KEY_INDEX])); 170 164 default: … … 180 174 nh_link); 181 175 182 while (!list_empty(&nodep->cs_ head)) {183 tmpfs_dentry_t *dentryp = list_get_instance( nodep->cs_head.next,184 tmpfs_dentry_t, link);176 while (!list_empty(&nodep->cs_list)) { 177 tmpfs_dentry_t *dentryp = list_get_instance( 178 list_first(&nodep->cs_list), tmpfs_dentry_t, link); 185 179 186 180 assert(nodep->type == TMPFS_DIRECTORY); … … 208 202 nodep->bp = NULL; 209 203 nodep->index = 0; 210 nodep-> devmap_handle= 0;204 nodep->service_id = 0; 211 205 nodep->type = TMPFS_NONE; 212 206 nodep->lnkcnt = 0; … … 214 208 nodep->data = NULL; 215 209 link_initialize(&nodep->nh_link); 216 list_initialize(&nodep->cs_ head);210 list_initialize(&nodep->cs_list); 217 211 } 218 212 … … 232 226 } 233 227 234 static bool tmpfs_instance_init( devmap_handle_t devmap_handle)228 static bool tmpfs_instance_init(service_id_t service_id) 235 229 { 236 230 fs_node_t *rfn; 237 231 int rc; 238 232 239 rc = tmpfs_create_node(&rfn, devmap_handle, L_DIRECTORY);233 rc = tmpfs_create_node(&rfn, service_id, L_DIRECTORY); 240 234 if (rc != EOK || !rfn) 241 235 return false; … … 244 238 } 245 239 246 static void tmpfs_instance_done( devmap_handle_t devmap_handle)247 { 248 unsigned long key[] = { 249 [NODES_KEY_DEV] = devmap_handle240 static void tmpfs_instance_done(service_id_t service_id) 241 { 242 unsigned long key[] = { 243 [NODES_KEY_DEV] = service_id 250 244 }; 251 245 /* … … 262 256 { 263 257 tmpfs_node_t *parentp = TMPFS_NODE(pfn); 264 link_t *lnk; 265 266 for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head; 267 lnk = lnk->next) { 258 259 list_foreach(parentp->cs_list, lnk) { 268 260 tmpfs_dentry_t *dentryp; 269 261 dentryp = list_get_instance(lnk, tmpfs_dentry_t, link); … … 278 270 } 279 271 280 int tmpfs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)281 { 282 unsigned long key[] = { 283 [NODES_KEY_DEV] = devmap_handle,272 int tmpfs_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index) 273 { 274 unsigned long key[] = { 275 [NODES_KEY_DEV] = service_id, 284 276 [NODES_KEY_INDEX] = index 285 277 }; … … 307 299 } 308 300 309 int tmpfs_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int lflag)301 int tmpfs_create_node(fs_node_t **rfn, service_id_t service_id, int lflag) 310 302 { 311 303 fs_node_t *rootfn; … … 326 318 nodep->bp->data = nodep; /* link the FS and TMPFS nodes */ 327 319 328 rc = tmpfs_root_get(&rootfn, devmap_handle);320 rc = tmpfs_root_get(&rootfn, service_id); 329 321 assert(rc == EOK); 330 322 if (!rootfn) … … 332 324 else 333 325 nodep->index = tmpfs_next_index++; 334 nodep-> devmap_handle = devmap_handle;326 nodep->service_id = service_id; 335 327 if (lflag & L_DIRECTORY) 336 328 nodep->type = TMPFS_DIRECTORY; … … 340 332 /* Insert the new node into the nodes hash table. */ 341 333 unsigned long key[] = { 342 [NODES_KEY_DEV] = nodep-> devmap_handle,334 [NODES_KEY_DEV] = nodep->service_id, 343 335 [NODES_KEY_INDEX] = nodep->index 344 336 }; … … 353 345 354 346 assert(!nodep->lnkcnt); 355 assert(list_empty(&nodep->cs_ head));356 357 unsigned long key[] = { 358 [NODES_KEY_DEV] = nodep-> devmap_handle,347 assert(list_empty(&nodep->cs_list)); 348 349 unsigned long key[] = { 350 [NODES_KEY_DEV] = nodep->service_id, 359 351 [NODES_KEY_INDEX] = nodep->index 360 352 }; … … 373 365 tmpfs_node_t *childp = TMPFS_NODE(cfn); 374 366 tmpfs_dentry_t *dentryp; 375 link_t *lnk;376 367 377 368 assert(parentp->type == TMPFS_DIRECTORY); 378 369 379 370 /* Check for duplicit entries. */ 380 for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head; 381 lnk = lnk->next) { 371 list_foreach(parentp->cs_list, lnk) { 382 372 dentryp = list_get_instance(lnk, tmpfs_dentry_t, link); 383 373 if (!str_cmp(dentryp->name, nm)) … … 401 391 dentryp->node = childp; 402 392 childp->lnkcnt++; 403 list_append(&dentryp->link, &parentp->cs_ head);393 list_append(&dentryp->link, &parentp->cs_list); 404 394 405 395 return EOK; … … 411 401 tmpfs_node_t *childp = NULL; 412 402 tmpfs_dentry_t *dentryp; 413 link_t *lnk;414 403 415 404 if (!parentp) 416 405 return EBUSY; 417 406 418 for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head; 419 lnk = lnk->next) { 407 list_foreach(parentp->cs_list, lnk) { 420 408 dentryp = list_get_instance(lnk, tmpfs_dentry_t, link); 421 409 if (!str_cmp(dentryp->name, nm)) { … … 423 411 assert(FS_NODE(childp) == cfn); 424 412 break; 425 } 413 } 426 414 } 427 415 … … 429 417 return ENOENT; 430 418 431 if ((childp->lnkcnt == 1) && !list_empty(&childp->cs_ head))419 if ((childp->lnkcnt == 1) && !list_empty(&childp->cs_list)) 432 420 return ENOTEMPTY; 433 421 … … 439 427 } 440 428 441 void tmpfs_mounted(ipc_callid_t rid, ipc_call_t *request) 442 { 443 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 429 /* 430 * Implementation of the VFS_OUT interface. 431 */ 432 433 static int 434 tmpfs_mounted(service_id_t service_id, const char *opts, 435 fs_index_t *index, aoff64_t *size, unsigned *lnkcnt) 436 { 444 437 fs_node_t *rootfn; 445 438 int rc; 446 439 447 /* Accept the mount options. */448 char *opts;449 rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);450 if (rc != EOK) {451 async_answer_0(rid, rc);452 return;453 }454 455 440 /* Check if this device is not already mounted. */ 456 rc = tmpfs_root_get(&rootfn, devmap_handle);441 rc = tmpfs_root_get(&rootfn, service_id); 457 442 if ((rc == EOK) && (rootfn)) { 458 443 (void) tmpfs_node_put(rootfn); 459 free(opts); 460 async_answer_0(rid, EEXIST); 461 return; 444 return EEXIST; 462 445 } 463 446 464 447 /* Initialize TMPFS instance. */ 465 if (!tmpfs_instance_init(devmap_handle)) { 466 free(opts); 467 async_answer_0(rid, ENOMEM); 468 return; 469 } 470 471 rc = tmpfs_root_get(&rootfn, devmap_handle); 448 if (!tmpfs_instance_init(service_id)) 449 return ENOMEM; 450 451 rc = tmpfs_root_get(&rootfn, service_id); 472 452 assert(rc == EOK); 473 453 tmpfs_node_t *rootp = TMPFS_NODE(rootfn); 474 454 if (str_cmp(opts, "restore") == 0) { 475 if (tmpfs_restore(devmap_handle)) 476 async_answer_3(rid, EOK, rootp->index, rootp->size, 477 rootp->lnkcnt); 478 else 479 async_answer_0(rid, ELIMIT); 480 } else { 481 async_answer_3(rid, EOK, rootp->index, rootp->size, 482 rootp->lnkcnt); 483 } 484 free(opts); 485 } 486 487 void tmpfs_mount(ipc_callid_t rid, ipc_call_t *request) 488 { 489 libfs_mount(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request); 490 } 491 492 void tmpfs_unmounted(ipc_callid_t rid, ipc_call_t *request) 493 { 494 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 495 496 tmpfs_instance_done(devmap_handle); 497 async_answer_0(rid, EOK); 498 } 499 500 void tmpfs_unmount(ipc_callid_t rid, ipc_call_t *request) 501 { 502 libfs_unmount(&tmpfs_libfs_ops, rid, request); 503 } 504 505 void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request) 506 { 507 libfs_lookup(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request); 508 } 509 510 void tmpfs_read(ipc_callid_t rid, ipc_call_t *request) 511 { 512 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 513 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 514 aoff64_t pos = 515 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request)); 516 455 if (!tmpfs_restore(service_id)) 456 return ELIMIT; 457 } 458 459 *index = rootp->index; 460 *size = rootp->size; 461 *lnkcnt = rootp->lnkcnt; 462 463 return EOK; 464 } 465 466 static int tmpfs_unmounted(service_id_t service_id) 467 { 468 tmpfs_instance_done(service_id); 469 return EOK; 470 } 471 472 static int tmpfs_read(service_id_t service_id, fs_index_t index, aoff64_t pos, 473 size_t *rbytes) 474 { 517 475 /* 518 476 * Lookup the respective TMPFS node. … … 520 478 link_t *hlp; 521 479 unsigned long key[] = { 522 [NODES_KEY_DEV] = devmap_handle,480 [NODES_KEY_DEV] = service_id, 523 481 [NODES_KEY_INDEX] = index 524 482 }; 525 483 hlp = hash_table_find(&nodes, key); 526 if (!hlp) { 527 async_answer_0(rid, ENOENT); 528 return; 529 } 484 if (!hlp) 485 return ENOENT; 530 486 tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t, 531 487 nh_link); … … 538 494 if (!async_data_read_receive(&callid, &size)) { 539 495 async_answer_0(callid, EINVAL); 540 async_answer_0(rid, EINVAL); 541 return; 496 return EINVAL; 542 497 } 543 498 … … 550 505 tmpfs_dentry_t *dentryp; 551 506 link_t *lnk; 552 aoff64_t i;553 507 554 508 assert(nodep->type == TMPFS_DIRECTORY); … … 559 513 * hash table. 560 514 */ 561 for (i = 0, lnk = nodep->cs_head.next; 562 (i < pos) && (lnk != &nodep->cs_head); 563 i++, lnk = lnk->next) 564 ; 565 566 if (lnk == &nodep->cs_head) { 515 lnk = list_nth(&nodep->cs_list, pos); 516 517 if (lnk == NULL) { 567 518 async_answer_0(callid, ENOENT); 568 async_answer_1(rid, ENOENT, 0); 569 return; 519 return ENOENT; 570 520 } 571 521 … … 577 527 } 578 528 579 /* 580 * Answer the VFS_READ call. 581 */ 582 async_answer_1(rid, EOK, bytes); 583 } 584 585 void tmpfs_write(ipc_callid_t rid, ipc_call_t *request) 586 { 587 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 588 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 589 aoff64_t pos = 590 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request)); 591 529 *rbytes = bytes; 530 return EOK; 531 } 532 533 static int 534 tmpfs_write(service_id_t service_id, fs_index_t index, aoff64_t pos, 535 size_t *wbytes, aoff64_t *nsize) 536 { 592 537 /* 593 538 * Lookup the respective TMPFS node. … … 595 540 link_t *hlp; 596 541 unsigned long key[] = { 597 [NODES_KEY_DEV] = devmap_handle,542 [NODES_KEY_DEV] = service_id, 598 543 [NODES_KEY_INDEX] = index 599 544 }; 600 545 hlp = hash_table_find(&nodes, key); 601 if (!hlp) { 602 async_answer_0(rid, ENOENT); 603 return; 604 } 546 if (!hlp) 547 return ENOENT; 605 548 tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t, 606 549 nh_link); … … 613 556 if (!async_data_write_receive(&callid, &size)) { 614 557 async_answer_0(callid, EINVAL); 615 async_answer_0(rid, EINVAL); 616 return; 558 return EINVAL; 617 559 } 618 560 … … 622 564 if (pos + size <= nodep->size) { 623 565 /* The file size is not changing. */ 624 (void) async_data_write_finalize(callid, nodep->data + pos, size);625 async_answer_2(rid, EOK, size, nodep->size);626 return;566 (void) async_data_write_finalize(callid, nodep->data + pos, 567 size); 568 goto out; 627 569 } 628 570 size_t delta = (pos + size) - nodep->size; … … 637 579 if (!newdata) { 638 580 async_answer_0(callid, ENOMEM); 639 async_answer_2(rid, EOK, 0, nodep->size);640 return;581 size = 0; 582 goto out; 641 583 } 642 584 /* Clear any newly allocated memory in order to emulate gaps. */ … … 645 587 nodep->data = newdata; 646 588 (void) async_data_write_finalize(callid, nodep->data + pos, size); 647 async_answer_2(rid, EOK, size, nodep->size); 648 } 649 650 void tmpfs_truncate(ipc_callid_t rid, ipc_call_t *request) 651 { 652 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 653 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 654 aoff64_t size = 655 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request)); 656 589 590 out: 591 *wbytes = size; 592 *nsize = nodep->size; 593 return EOK; 594 } 595 596 static int tmpfs_truncate(service_id_t service_id, fs_index_t index, 597 aoff64_t size) 598 { 657 599 /* 658 600 * Lookup the respective TMPFS node. 659 601 */ 660 602 unsigned long key[] = { 661 [NODES_KEY_DEV] = devmap_handle,603 [NODES_KEY_DEV] = service_id, 662 604 [NODES_KEY_INDEX] = index 663 605 }; 664 606 link_t *hlp = hash_table_find(&nodes, key); 665 if (!hlp) { 666 async_answer_0(rid, ENOENT); 667 return; 668 } 669 tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t, 670 nh_link); 671 672 if (size == nodep->size) { 673 async_answer_0(rid, EOK); 674 return; 675 } 676 677 if (size > SIZE_MAX) { 678 async_answer_0(rid, ENOMEM); 679 return; 680 } 607 if (!hlp) 608 return ENOENT; 609 tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t, nh_link); 610 611 if (size == nodep->size) 612 return EOK; 613 614 if (size > SIZE_MAX) 615 return ENOMEM; 681 616 682 617 void *newdata = realloc(nodep->data, size); 683 if (!newdata) { 684 async_answer_0(rid, ENOMEM); 685 return; 686 } 618 if (!newdata) 619 return ENOMEM; 687 620 688 621 if (size > nodep->size) { … … 693 626 nodep->size = size; 694 627 nodep->data = newdata; 695 async_answer_0(rid, EOK); 696 } 697 698 void tmpfs_close(ipc_callid_t rid, ipc_call_t *request) 699 { 700 async_answer_0(rid, EOK); 701 } 702 703 void tmpfs_destroy(ipc_callid_t rid, ipc_call_t *request) 704 { 705 devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request); 706 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 707 int rc; 708 628 return EOK; 629 } 630 631 static int tmpfs_close(service_id_t service_id, fs_index_t index) 632 { 633 return EOK; 634 } 635 636 static int tmpfs_destroy(service_id_t service_id, fs_index_t index) 637 { 709 638 link_t *hlp; 710 639 unsigned long key[] = { 711 [NODES_KEY_DEV] = devmap_handle,640 [NODES_KEY_DEV] = service_id, 712 641 [NODES_KEY_INDEX] = index 713 642 }; 714 643 hlp = hash_table_find(&nodes, key); 715 if (!hlp) { 716 async_answer_0(rid, ENOENT); 717 return; 718 } 644 if (!hlp) 645 return ENOENT; 719 646 tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t, 720 647 nh_link); 721 rc = tmpfs_destroy_node(FS_NODE(nodep)); 722 async_answer_0(rid, rc); 723 } 724 725 void tmpfs_open_node(ipc_callid_t rid, ipc_call_t *request) 726 { 727 libfs_open_node(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request); 728 } 729 730 void tmpfs_stat(ipc_callid_t rid, ipc_call_t *request) 731 { 732 libfs_stat(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request); 733 } 734 735 void tmpfs_sync(ipc_callid_t rid, ipc_call_t *request) 648 return tmpfs_destroy_node(FS_NODE(nodep)); 649 } 650 651 static int tmpfs_sync(service_id_t service_id, fs_index_t index) 736 652 { 737 653 /* … … 739 655 * thus the sync operation is a no-op. 740 656 */ 741 async_answer_0(rid, EOK); 742 } 657 return EOK; 658 } 659 660 vfs_out_ops_t tmpfs_ops = { 661 .mounted = tmpfs_mounted, 662 .unmounted = tmpfs_unmounted, 663 .read = tmpfs_read, 664 .write = tmpfs_write, 665 .truncate = tmpfs_truncate, 666 .close = tmpfs_close, 667 .destroy = tmpfs_destroy, 668 .sync = tmpfs_sync, 669 }; 743 670 744 671 /** 745 672 * @} 746 673 */ 674
Note:
See TracChangeset
for help on using the changeset viewer.