Changeset c05642d in mainline for uspace/srv
- Timestamp:
- 2011-09-07T00:03:26Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 5081276
- Parents:
- bb74dabe (diff), 038b289 (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
- Files:
-
- 30 added
- 18 edited
-
bd/ata_bd/ata_bd.c (modified) (3 diffs)
-
bd/ata_bd/ata_hw.h (modified) (2 diffs)
-
devman/devman.c (modified) (40 diffs)
-
devman/devman.h (modified) (6 diffs)
-
devman/main.c (modified) (29 diffs)
-
fs/cdfs/Makefile (added)
-
fs/cdfs/cdfs.c (added)
-
fs/cdfs/cdfs.h (added)
-
fs/cdfs/cdfs_endian.h (added)
-
fs/cdfs/cdfs_ops.c (added)
-
fs/cdfs/cdfs_ops.h (added)
-
fs/exfat/Makefile (added)
-
fs/exfat/exfat.c (added)
-
fs/exfat/exfat.h (added)
-
fs/exfat/exfat_bitmap.c (added)
-
fs/exfat/exfat_bitmap.h (added)
-
fs/exfat/exfat_dentry.c (added)
-
fs/exfat/exfat_dentry.h (added)
-
fs/exfat/exfat_directory.c (added)
-
fs/exfat/exfat_directory.h (added)
-
fs/exfat/exfat_fat.c (added)
-
fs/exfat/exfat_fat.h (added)
-
fs/exfat/exfat_idx.c (added)
-
fs/exfat/exfat_ops.c (added)
-
fs/ext2fs/ext2fs_ops.c (modified) (3 diffs)
-
fs/fat/Makefile (modified) (1 diff)
-
fs/fat/fat.c (modified) (1 diff)
-
fs/fat/fat.h (modified) (3 diffs)
-
fs/fat/fat_dentry.c (modified) (5 diffs)
-
fs/fat/fat_dentry.h (modified) (5 diffs)
-
fs/fat/fat_directory.c (added)
-
fs/fat/fat_directory.h (added)
-
fs/fat/fat_fat.c (modified) (29 diffs)
-
fs/fat/fat_fat.h (modified) (5 diffs)
-
fs/fat/fat_idx.c (modified) (13 diffs)
-
fs/fat/fat_ops.c (modified) (44 diffs)
-
fs/locfs/locfs_ops.c (modified) (2 diffs)
-
fs/mfs/Makefile (added)
-
fs/mfs/mfs.c (added)
-
fs/mfs/mfs.h (added)
-
fs/mfs/mfs_balloc.c (added)
-
fs/mfs/mfs_dentry.c (added)
-
fs/mfs/mfs_inode.c (added)
-
fs/mfs/mfs_ops.c (added)
-
fs/mfs/mfs_rw.c (added)
-
fs/mfs/mfs_utils.c (added)
-
fs/tmpfs/tmpfs_ops.c (modified) (2 diffs)
-
loc/loc.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/bd/ata_bd/ata_bd.c
rbb74dabe rc05642d 118 118 static int ata_pcmd_inquiry(int dev_idx, void *obuf, size_t obuf_size); 119 119 static int ata_pcmd_read_12(int dev_idx, uint64_t ba, size_t cnt, 120 void *obuf, size_t obuf_size); 121 static int ata_pcmd_read_toc(int dev_idx, uint8_t ses, 120 122 void *obuf, size_t obuf_size); 121 123 static void disk_print_summary(disk_t *d); … … 353 355 UPPER32(disk[disk_id].blocks)); 354 356 continue; 357 case BD_READ_TOC: 358 cnt = IPC_GET_ARG1(call); 359 if (disk[disk_id].dev_type == ata_pkt_dev) 360 retval = ata_pcmd_read_toc(disk_id, cnt, fs_va, 361 disk[disk_id].block_size); 362 else 363 retval = EINVAL; 364 break; 355 365 default: 356 366 retval = EINVAL; … … 810 820 } 811 821 822 /** Issue ATAPI read TOC command. 823 * 824 * Read TOC in 'multi-session' format (first and last session number 825 * with last session LBA). 826 * 827 * http://suif.stanford.edu/~csapuntz/specs/INF-8020.PDF page 171 828 * 829 * Output buffer must be large enough to hold the data, otherwise the 830 * function will fail. 831 * 832 * @param dev_idx Device index (0 or 1) 833 * @param session Starting session 834 * @param obuf Buffer for storing inquiry data read from device 835 * @param obuf_size Size of obuf in bytes 836 * 837 * @return EOK on success, EIO on error. 838 */ 839 static int ata_pcmd_read_toc(int dev_idx, uint8_t session, void *obuf, 840 size_t obuf_size) 841 { 842 ata_pcmd_read_toc_t cp; 843 int rc; 844 845 memset(&cp, 0, sizeof(cp)); 846 847 cp.opcode = PCMD_READ_TOC; 848 cp.msf = 0; 849 cp.format = 0x01; /* 0x01 = multi-session mode */ 850 cp.start = session; 851 cp.size = host2uint16_t_be(obuf_size); 852 cp.oldformat = 0x40; /* 0x01 = multi-session mode (shifted to MSB) */ 853 854 rc = ata_cmd_packet(0, &cp, sizeof(cp), obuf, obuf_size); 855 if (rc != EOK) 856 return rc; 857 858 return EOK; 859 } 860 812 861 /** Read a physical from the device. 813 862 * -
uspace/srv/bd/ata_bd/ata_hw.h
rbb74dabe rc05642d 244 244 enum ata_pkt_command { 245 245 PCMD_INQUIRY = 0x12, 246 PCMD_READ_12 = 0xa8 246 PCMD_READ_12 = 0xa8, 247 PCMD_READ_TOC = 0x43 247 248 }; 248 249 … … 269 270 uint8_t _res2; 270 271 } __attribute__ ((packed)) ata_pcmd_read_12_t; 272 273 /** ATAPI Read TOC command */ 274 typedef struct { 275 uint8_t opcode; /**< Operation code (PCMD_READ_TOC) */ 276 uint8_t msf; /**< 0x2 = MSF bit set */ 277 uint8_t format; /**< low 3 bits */ 278 uint8_t _res0; 279 uint8_t _res1; 280 uint8_t _res2; 281 uint8_t start; /**< starting track/session number */ 282 uint16_t size; /**< Allocation length */ 283 uint8_t oldformat; /**< high 2 bits */ 284 uint8_t _res3; 285 uint8_t _res4; 286 } __attribute__ ((packed)) ata_pcmd_read_toc_t; 271 287 272 288 /** Data returned from Inquiry command (mandatory part) */ -
uspace/srv/devman/devman.c
rbb74dabe rc05642d 30 30 * @{ 31 31 */ 32 /** @file Device Manager 33 * 34 * Locking order: 35 * (1) driver_t.driver_mutex 36 * (2) dev_tree_t.rwlock 37 * 38 * Synchronization: 39 * - device_tree.rwlock protects: 40 * - tree root, complete tree topology 41 * - complete contents of device and function nodes 42 * - dev_node_t.refcnt, fun_node_t.refcnt prevent nodes from 43 * being deallocated 44 * - find_xxx() functions increase reference count of returned object 45 * - find_xxx_no_lock() do not increase reference count 46 * 47 * TODO 48 * - Track all steady and transient device/function states 49 * - Check states, wait for steady state on certain operations 50 */ 32 51 33 52 #include <errno.h> … … 43 62 #include "devman.h" 44 63 45 fun_node_t *find_node_child(fun_node_t *parent, const char *name);64 static fun_node_t *find_node_child(dev_tree_t *, fun_node_t *, const char *); 46 65 47 66 /* hash table operations */ … … 406 425 } 407 426 427 fun_add_ref(fun); 408 428 insert_fun_node(tree, fun, str_dup(""), NULL); 429 409 430 match_id_t *id = create_match_id(); 410 431 id->id = str_dup("root"); … … 422 443 } 423 444 445 dev_add_ref(dev); 424 446 insert_dev_node(tree, dev, fun); 425 447 … … 467 489 /** Assign a driver to a device. 468 490 * 491 * @param tree Device tree 469 492 * @param node The device's node in the device tree. 470 493 * @param drv The driver. 471 494 */ 472 void attach_driver(dev_ node_t *dev, driver_t *drv)495 void attach_driver(dev_tree_t *tree, dev_node_t *dev, driver_t *drv) 473 496 { 474 497 log_msg(LVL_DEBUG, "attach_driver(dev=\"%s\",drv=\"%s\")", … … 476 499 477 500 fibril_mutex_lock(&drv->driver_mutex); 501 fibril_rwlock_write_lock(&tree->rwlock); 478 502 479 503 dev->drv = drv; 480 504 list_append(&dev->driver_devices, &drv->devices); 481 505 506 fibril_rwlock_write_unlock(&tree->rwlock); 507 fibril_mutex_unlock(&drv->driver_mutex); 508 } 509 510 /** Detach driver from device. 511 * 512 * @param tree Device tree 513 * @param node The device's node in the device tree. 514 * @param drv The driver. 515 */ 516 void detach_driver(dev_tree_t *tree, dev_node_t *dev) 517 { 518 driver_t *drv = dev->drv; 519 520 assert(drv != NULL); 521 522 log_msg(LVL_DEBUG, "detach_driver(dev=\"%s\",drv=\"%s\")", 523 dev->pfun->pathname, drv->name); 524 525 fibril_mutex_lock(&drv->driver_mutex); 526 fibril_rwlock_write_lock(&tree->rwlock); 527 528 dev->drv = NULL; 529 list_remove(&dev->driver_devices); 530 531 fibril_rwlock_write_unlock(&tree->rwlock); 482 532 fibril_mutex_unlock(&drv->driver_mutex); 483 533 } … … 556 606 while (link != &driver->devices.head) { 557 607 dev = list_get_instance(link, dev_node_t, driver_devices); 608 fibril_rwlock_write_lock(&tree->rwlock); 609 558 610 if (dev->passed_to_driver) { 611 fibril_rwlock_write_unlock(&tree->rwlock); 559 612 link = link->next; 560 613 continue; 561 614 } 562 615 563 /* 564 * We remove the device from the list to allow safe adding 565 * of new devices (no one will touch our item this way). 566 */ 567 list_remove(link); 616 log_msg(LVL_DEBUG, "pass_devices_to_driver: dev->refcnt=%d\n", 617 (int)atomic_get(&dev->refcnt)); 618 dev_add_ref(dev); 568 619 569 620 /* … … 572 623 */ 573 624 fibril_mutex_unlock(&driver->driver_mutex); 625 fibril_rwlock_write_unlock(&tree->rwlock); 574 626 575 627 add_device(driver, dev, tree); 628 629 dev_del_ref(dev); 576 630 577 631 /* … … 580 634 */ 581 635 fibril_mutex_lock(&driver->driver_mutex); 582 583 /*584 * Insert the device back.585 * The order is not relevant here so no harm is done586 * (actually, the order would be preserved in most cases).587 */588 list_append(link, &driver->devices);589 636 590 637 /* … … 679 726 char *loc_name = NULL; 680 727 728 assert(fibril_rwlock_is_locked(&tree->rwlock)); 729 681 730 asprintf(&loc_name, "%s", fun->pathname); 682 731 if (loc_name == NULL) … … 726 775 727 776 ipc_call_t answer; 728 aid_t req = async_send_2(exch, DRIVER_ ADD_DEVICE, dev->handle,777 aid_t req = async_send_2(exch, DRIVER_DEV_ADD, dev->handle, 729 778 parent_handle, &answer); 730 779 … … 783 832 784 833 /* Attach the driver to the device. */ 785 attach_driver( dev, drv);834 attach_driver(tree, dev, drv); 786 835 787 836 fibril_mutex_lock(&drv->driver_mutex); … … 797 846 add_device(drv, dev, tree); 798 847 848 fibril_mutex_lock(&drv->driver_mutex); 849 fibril_mutex_unlock(&drv->driver_mutex); 850 851 fibril_rwlock_write_lock(&tree->rwlock); 852 if (dev->pfun != NULL) { 853 dev->pfun->state = FUN_ON_LINE; 854 } 855 fibril_rwlock_write_unlock(&tree->rwlock); 799 856 return true; 857 } 858 859 int driver_dev_remove(dev_tree_t *tree, dev_node_t *dev) 860 { 861 async_exch_t *exch; 862 sysarg_t retval; 863 driver_t *drv; 864 devman_handle_t handle; 865 866 assert(dev != NULL); 867 868 log_msg(LVL_DEBUG, "driver_dev_remove(%p)", dev); 869 870 fibril_rwlock_read_lock(&tree->rwlock); 871 drv = dev->drv; 872 handle = dev->handle; 873 fibril_rwlock_read_unlock(&tree->rwlock); 874 875 exch = async_exchange_begin(drv->sess); 876 retval = async_req_1_0(exch, DRIVER_DEV_REMOVE, handle); 877 async_exchange_end(exch); 878 879 return retval; 880 } 881 882 int driver_dev_gone(dev_tree_t *tree, dev_node_t *dev) 883 { 884 async_exch_t *exch; 885 sysarg_t retval; 886 driver_t *drv; 887 devman_handle_t handle; 888 889 assert(dev != NULL); 890 891 log_msg(LVL_DEBUG, "driver_dev_gone(%p)", dev); 892 893 fibril_rwlock_read_lock(&tree->rwlock); 894 drv = dev->drv; 895 handle = dev->handle; 896 fibril_rwlock_read_unlock(&tree->rwlock); 897 898 exch = async_exchange_begin(drv->sess); 899 retval = async_req_1_0(exch, DRIVER_DEV_GONE, handle); 900 async_exchange_end(exch); 901 902 return retval; 903 } 904 905 int driver_fun_online(dev_tree_t *tree, fun_node_t *fun) 906 { 907 async_exch_t *exch; 908 sysarg_t retval; 909 driver_t *drv; 910 devman_handle_t handle; 911 912 log_msg(LVL_DEBUG, "driver_fun_online(%p)", fun); 913 914 fibril_rwlock_read_lock(&tree->rwlock); 915 916 if (fun->dev == NULL) { 917 /* XXX root function? */ 918 fibril_rwlock_read_unlock(&tree->rwlock); 919 return EINVAL; 920 } 921 922 drv = fun->dev->drv; 923 handle = fun->handle; 924 fibril_rwlock_read_unlock(&tree->rwlock); 925 926 exch = async_exchange_begin(drv->sess); 927 retval = async_req_1_0(exch, DRIVER_FUN_ONLINE, handle); 928 loc_exchange_end(exch); 929 930 return retval; 931 } 932 933 int driver_fun_offline(dev_tree_t *tree, fun_node_t *fun) 934 { 935 async_exch_t *exch; 936 sysarg_t retval; 937 driver_t *drv; 938 devman_handle_t handle; 939 940 log_msg(LVL_DEBUG, "driver_fun_offline(%p)", fun); 941 942 fibril_rwlock_read_lock(&tree->rwlock); 943 if (fun->dev == NULL) { 944 /* XXX root function? */ 945 fibril_rwlock_read_unlock(&tree->rwlock); 946 return EINVAL; 947 } 948 949 drv = fun->dev->drv; 950 handle = fun->handle; 951 fibril_rwlock_read_unlock(&tree->rwlock); 952 953 exch = async_exchange_begin(drv->sess); 954 retval = async_req_1_0(exch, DRIVER_FUN_OFFLINE, handle); 955 loc_exchange_end(exch); 956 957 return retval; 958 800 959 } 801 960 … … 826 985 if (!create_root_nodes(tree)) 827 986 return false; 828 987 829 988 /* Find suitable driver and start it. */ 830 return assign_driver(tree->root_node->child, drivers_list, tree); 989 dev_node_t *rdev = tree->root_node->child; 990 dev_add_ref(rdev); 991 int rc = assign_driver(rdev, drivers_list, tree); 992 dev_del_ref(rdev); 993 994 return rc; 831 995 } 832 996 … … 839 1003 dev_node_t *create_dev_node(void) 840 1004 { 841 dev_node_t *res = malloc(sizeof(dev_node_t)); 842 843 if (res != NULL) { 844 memset(res, 0, sizeof(dev_node_t)); 845 list_initialize(&res->functions); 846 link_initialize(&res->driver_devices); 847 link_initialize(&res->devman_dev); 848 } 849 850 return res; 1005 dev_node_t *dev; 1006 1007 dev = calloc(1, sizeof(dev_node_t)); 1008 if (dev == NULL) 1009 return NULL; 1010 1011 atomic_set(&dev->refcnt, 0); 1012 list_initialize(&dev->functions); 1013 link_initialize(&dev->driver_devices); 1014 link_initialize(&dev->devman_dev); 1015 1016 return dev; 851 1017 } 852 1018 … … 864 1030 } 865 1031 1032 /** Increase device node reference count. 1033 * 1034 * @param dev Device node 1035 */ 1036 void dev_add_ref(dev_node_t *dev) 1037 { 1038 atomic_inc(&dev->refcnt); 1039 } 1040 1041 /** Decrease device node reference count. 1042 * 1043 * When the count drops to zero the device node is freed. 1044 * 1045 * @param dev Device node 1046 */ 1047 void dev_del_ref(dev_node_t *dev) 1048 { 1049 if (atomic_predec(&dev->refcnt) == 0) 1050 delete_dev_node(dev); 1051 } 1052 1053 866 1054 /** Find the device node structure of the device witch has the specified handle. 867 1055 * … … 893 1081 fibril_rwlock_read_lock(&tree->rwlock); 894 1082 dev = find_dev_node_no_lock(tree, handle); 1083 if (dev != NULL) 1084 dev_add_ref(dev); 1085 895 1086 fibril_rwlock_read_unlock(&tree->rwlock); 896 1087 … … 920 1111 list_get_instance(item, fun_node_t, dev_functions); 921 1112 922 if (pos < buf_cnt) 1113 if (pos < buf_cnt) { 923 1114 hdl_buf[pos] = fun->handle; 1115 } 1116 924 1117 pos++; 925 1118 } … … 937 1130 fun_node_t *create_fun_node(void) 938 1131 { 939 fun_node_t *res = malloc(sizeof(fun_node_t)); 940 941 if (res != NULL) { 942 memset(res, 0, sizeof(fun_node_t)); 943 link_initialize(&res->dev_functions); 944 list_initialize(&res->match_ids.ids); 945 link_initialize(&res->devman_fun); 946 link_initialize(&res->loc_fun); 947 } 948 949 return res; 1132 fun_node_t *fun; 1133 1134 fun = calloc(1, sizeof(fun_node_t)); 1135 if (fun == NULL) 1136 return NULL; 1137 1138 fun->state = FUN_INIT; 1139 atomic_set(&fun->refcnt, 0); 1140 link_initialize(&fun->dev_functions); 1141 list_initialize(&fun->match_ids.ids); 1142 link_initialize(&fun->devman_fun); 1143 link_initialize(&fun->loc_fun); 1144 1145 return fun; 950 1146 } 951 1147 … … 965 1161 } 966 1162 1163 /** Increase function node reference count. 1164 * 1165 * @param fun Function node 1166 */ 1167 void fun_add_ref(fun_node_t *fun) 1168 { 1169 atomic_inc(&fun->refcnt); 1170 } 1171 1172 /** Decrease function node reference count. 1173 * 1174 * When the count drops to zero the function node is freed. 1175 * 1176 * @param fun Function node 1177 */ 1178 void fun_del_ref(fun_node_t *fun) 1179 { 1180 if (atomic_predec(&fun->refcnt) == 0) 1181 delete_fun_node(fun); 1182 } 1183 967 1184 /** Find the function node with the specified handle. 968 1185 * … … 975 1192 unsigned long key = handle; 976 1193 link_t *link; 1194 fun_node_t *fun; 977 1195 978 1196 assert(fibril_rwlock_is_locked(&tree->rwlock)); … … 982 1200 return NULL; 983 1201 984 return hash_table_get_instance(link, fun_node_t, devman_fun); 1202 fun = hash_table_get_instance(link, fun_node_t, devman_fun); 1203 1204 return fun; 985 1205 } 986 1206 … … 996 1216 997 1217 fibril_rwlock_read_lock(&tree->rwlock); 1218 998 1219 fun = find_fun_node_no_lock(tree, handle); 1220 if (fun != NULL) 1221 fun_add_ref(fun); 1222 999 1223 fibril_rwlock_read_unlock(&tree->rwlock); 1000 1224 … … 1004 1228 /** Create and set device's full path in device tree. 1005 1229 * 1230 * @param tree Device tree 1006 1231 * @param node The device's device node. 1007 1232 * @param parent The parent device node. … … 1009 1234 * resources etc.). 1010 1235 */ 1011 static bool set_fun_path(fun_node_t *fun, fun_node_t *parent) 1012 { 1236 static bool set_fun_path(dev_tree_t *tree, fun_node_t *fun, fun_node_t *parent) 1237 { 1238 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1013 1239 assert(fun->name != NULL); 1014 1240 … … 1037 1263 * 1038 1264 * @param tree The device tree. 1039 * @param node The newly added device node. 1040 * @param dev_name The name of the newly added device. 1041 * @param parent The parent device node. 1265 * @param dev The newly added device node. 1266 * @param pfun The parent function node. 1042 1267 * 1043 1268 * @return True on success, false otherwise (insufficient resources … … 1046 1271 bool insert_dev_node(dev_tree_t *tree, dev_node_t *dev, fun_node_t *pfun) 1047 1272 { 1048 assert(dev != NULL);1049 assert(tree != NULL);1050 1273 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1051 1274 … … 1065 1288 } 1066 1289 1290 /** Remove device from device tree. 1291 * 1292 * @param tree Device tree 1293 * @param dev Device node 1294 */ 1295 void remove_dev_node(dev_tree_t *tree, dev_node_t *dev) 1296 { 1297 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1298 1299 log_msg(LVL_DEBUG, "remove_dev_node(dev=%p)", dev); 1300 1301 /* Remove node from the handle-to-node map. */ 1302 unsigned long key = dev->handle; 1303 hash_table_remove(&tree->devman_devices, &key, 1); 1304 1305 /* Unlink from parent function. */ 1306 dev->pfun->child = NULL; 1307 dev->pfun = NULL; 1308 1309 dev->state = DEVICE_REMOVED; 1310 } 1311 1312 1067 1313 /** Insert new function into device tree. 1068 1314 * 1069 1315 * @param tree The device tree. 1070 * @param nodeThe newly added function node.1071 * @param dev_name The name of the newly added function.1072 * @param parentOwning device node.1316 * @param fun The newly added function node. 1317 * @param fun_name The name of the newly added function. 1318 * @param dev Owning device node. 1073 1319 * 1074 1320 * @return True on success, false otherwise (insufficient resources … … 1080 1326 fun_node_t *pfun; 1081 1327 1082 assert(fun != NULL);1083 assert(tree != NULL);1084 1328 assert(fun_name != NULL); 1085 1329 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); … … 1092 1336 1093 1337 fun->name = fun_name; 1094 if (!set_fun_path( fun, pfun)) {1338 if (!set_fun_path(tree, fun, pfun)) { 1095 1339 return false; 1096 1340 } … … 1116 1360 void remove_fun_node(dev_tree_t *tree, fun_node_t *fun) 1117 1361 { 1118 assert(tree != NULL);1119 assert(fun != NULL);1120 1362 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1121 1363 … … 1127 1369 if (fun->dev != NULL) 1128 1370 list_remove(&fun->dev_functions); 1371 1372 fun->dev = NULL; 1373 fun->state = FUN_REMOVED; 1129 1374 } 1130 1375 … … 1148 1393 1149 1394 fun_node_t *fun = tree->root_node; 1395 fun_add_ref(fun); 1150 1396 /* 1151 1397 * Relative path to the function from its parent (but with '/' at the … … 1165 1411 } 1166 1412 1167 fun = find_node_child(fun, rel_path + 1); 1413 fun_node_t *cfun = find_node_child(tree, fun, rel_path + 1); 1414 fun_del_ref(fun); 1415 fun = cfun; 1168 1416 1169 1417 if (cont) { … … 1183 1431 * Device tree rwlock should be held at least for reading. 1184 1432 * 1433 * @param tree Device tree 1185 1434 * @param dev Device the function belongs to. 1186 1435 * @param name Function name (not path). … … 1188 1437 * @retval NULL No function with given name. 1189 1438 */ 1190 fun_node_t *find_fun_node_in_device(dev_ node_t *dev, const char *name)1191 { 1192 assert(dev != NULL); 1439 fun_node_t *find_fun_node_in_device(dev_tree_t *tree, dev_node_t *dev, 1440 const char *name) 1441 { 1193 1442 assert(name != NULL); 1443 assert(fibril_rwlock_is_locked(&tree->rwlock)); 1194 1444 1195 1445 fun_node_t *fun; … … 1198 1448 fun = list_get_instance(link, fun_node_t, dev_functions); 1199 1449 1200 if (str_cmp(name, fun->name) == 0) 1450 if (str_cmp(name, fun->name) == 0) { 1451 fun_add_ref(fun); 1201 1452 return fun; 1453 } 1202 1454 } 1203 1455 … … 1209 1461 * Device tree rwlock should be held at least for reading. 1210 1462 * 1463 * @param tree Device tree 1211 1464 * @param parent The parent function node. 1212 1465 * @param name The name of the child function. 1213 1466 * @return The child function node. 1214 1467 */ 1215 fun_node_t *find_node_child(fun_node_t *pfun, const char *name) 1216 { 1217 return find_fun_node_in_device(pfun->child, name); 1468 static fun_node_t *find_node_child(dev_tree_t *tree, fun_node_t *pfun, 1469 const char *name) 1470 { 1471 return find_fun_node_in_device(tree, pfun->child, name); 1218 1472 } 1219 1473 … … 1228 1482 fibril_rwlock_read_lock(&tree->rwlock); 1229 1483 link = hash_table_find(&tree->loc_functions, &key); 1230 if (link != NULL) 1484 if (link != NULL) { 1231 1485 fun = hash_table_get_instance(link, fun_node_t, loc_fun); 1486 fun_add_ref(fun); 1487 } 1232 1488 fibril_rwlock_read_unlock(&tree->rwlock); 1233 1489 … … 1237 1493 void tree_add_loc_function(dev_tree_t *tree, fun_node_t *fun) 1238 1494 { 1495 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1496 1239 1497 unsigned long key = (unsigned long) fun->service_id; 1240 fibril_rwlock_write_lock(&tree->rwlock);1241 1498 hash_table_insert(&tree->loc_functions, &key, &fun->loc_fun); 1242 fibril_rwlock_write_unlock(&tree->rwlock);1243 1499 } 1244 1500 -
uspace/srv/devman/devman.h
rbb74dabe rc05642d 118 118 } driver_list_t; 119 119 120 /** The state of the device.*/120 /** Device state */ 121 121 typedef enum { 122 122 DEVICE_NOT_INITIALIZED = 0, 123 123 DEVICE_USABLE, 124 124 DEVICE_NOT_PRESENT, 125 DEVICE_INVALID 125 DEVICE_INVALID, 126 /** Device node has been removed from the tree */ 127 DEVICE_REMOVED 126 128 } device_state_t; 127 129 128 130 /** Device node in the device tree. */ 129 131 struct dev_node { 132 /** Reference count */ 133 atomic_t refcnt; 134 130 135 /** The global unique identifier of the device. */ 131 136 devman_handle_t handle; … … 154 159 }; 155 160 161 /** Function state */ 162 typedef enum { 163 FUN_INIT = 0, 164 FUN_OFF_LINE, 165 FUN_ON_LINE, 166 /** Function node has been removed from the tree */ 167 FUN_REMOVED 168 } fun_state_t; 169 156 170 /** Function node in the device tree. */ 157 171 struct fun_node { 172 /** Reference count */ 173 atomic_t refcnt; 174 /** State */ 175 fun_state_t state; 176 158 177 /** The global unique identifier of the function */ 159 178 devman_handle_t handle; … … 239 258 240 259 extern void add_driver(driver_list_t *, driver_t *); 241 extern void attach_driver(dev_node_t *, driver_t *); 260 extern void attach_driver(dev_tree_t *, dev_node_t *, driver_t *); 261 extern void detach_driver(dev_tree_t *, dev_node_t *); 242 262 extern void add_device(driver_t *, dev_node_t *, dev_tree_t *); 243 263 extern bool start_driver(driver_t *); 264 extern int driver_dev_remove(dev_tree_t *, dev_node_t *); 265 extern int driver_dev_gone(dev_tree_t *, dev_node_t *); 266 extern int driver_fun_online(dev_tree_t *, fun_node_t *); 267 extern int driver_fun_offline(dev_tree_t *, fun_node_t *); 244 268 245 269 extern driver_t *find_driver(driver_list_t *, const char *); … … 254 278 extern dev_node_t *create_dev_node(void); 255 279 extern void delete_dev_node(dev_node_t *node); 280 extern void dev_add_ref(dev_node_t *); 281 extern void dev_del_ref(dev_node_t *); 256 282 extern dev_node_t *find_dev_node_no_lock(dev_tree_t *tree, 257 283 devman_handle_t handle); … … 263 289 extern fun_node_t *create_fun_node(void); 264 290 extern void delete_fun_node(fun_node_t *); 291 extern void fun_add_ref(fun_node_t *); 292 extern void fun_del_ref(fun_node_t *); 265 293 extern fun_node_t *find_fun_node_no_lock(dev_tree_t *tree, 266 294 devman_handle_t handle); 267 295 extern fun_node_t *find_fun_node(dev_tree_t *tree, devman_handle_t handle); 268 296 extern fun_node_t *find_fun_node_by_path(dev_tree_t *, char *); 269 extern fun_node_t *find_fun_node_in_device(dev_node_t *, const char *); 297 extern fun_node_t *find_fun_node_in_device(dev_tree_t *tree, dev_node_t *, 298 const char *); 270 299 271 300 /* Device tree */ … … 274 303 extern bool create_root_nodes(dev_tree_t *); 275 304 extern bool insert_dev_node(dev_tree_t *, dev_node_t *, fun_node_t *); 305 extern void remove_dev_node(dev_tree_t *, dev_node_t *); 276 306 extern bool insert_fun_node(dev_tree_t *, fun_node_t *, char *, dev_node_t *); 277 307 extern void remove_fun_node(dev_tree_t *, fun_node_t *); -
uspace/srv/devman/main.c
rbb74dabe rc05642d 234 234 dev_node_t *dev_node = (dev_node_t *) arg; 235 235 assign_driver(dev_node, &drivers_list, &device_tree); 236 237 /* Delete one reference we got from the caller. */ 238 dev_del_ref(dev_node); 236 239 return EOK; 237 240 } 238 241 239 /** Handle function registration. 240 * 241 * Child devices are registered by their parent's device driver. 242 */ 243 static void devman_add_function(ipc_callid_t callid, ipc_call_t *call) 244 { 245 fun_type_t ftype = (fun_type_t) IPC_GET_ARG1(*call); 246 devman_handle_t dev_handle = IPC_GET_ARG2(*call); 247 sysarg_t match_count = IPC_GET_ARG3(*call); 248 dev_tree_t *tree = &device_tree; 249 250 fibril_rwlock_write_lock(&tree->rwlock); 251 252 dev_node_t *dev = NULL; 253 dev_node_t *pdev = find_dev_node_no_lock(&device_tree, dev_handle); 254 255 if (pdev == NULL) { 256 fibril_rwlock_write_unlock(&tree->rwlock); 257 async_answer_0(callid, ENOENT); 258 return; 259 } 260 261 if (ftype != fun_inner && ftype != fun_exposed) { 262 /* Unknown function type */ 263 log_msg(LVL_ERROR, 264 "Unknown function type %d provided by driver.", 265 (int) ftype); 266 267 fibril_rwlock_write_unlock(&tree->rwlock); 268 async_answer_0(callid, EINVAL); 269 return; 270 } 271 272 char *fun_name = NULL; 273 int rc = async_data_write_accept((void **)&fun_name, true, 0, 0, 0, 0); 274 if (rc != EOK) { 275 fibril_rwlock_write_unlock(&tree->rwlock); 276 async_answer_0(callid, rc); 277 return; 278 } 279 280 /* Check that function with same name is not there already. */ 281 if (find_fun_node_in_device(pdev, fun_name) != NULL) { 282 fibril_rwlock_write_unlock(&tree->rwlock); 283 async_answer_0(callid, EEXISTS); 284 printf(NAME ": Warning, driver tried to register `%s' twice.\n", 285 fun_name); 286 free(fun_name); 287 return; 288 } 289 290 fun_node_t *fun = create_fun_node(); 291 fun->ftype = ftype; 292 293 if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) { 294 fibril_rwlock_write_unlock(&tree->rwlock); 295 delete_fun_node(fun); 296 async_answer_0(callid, ENOMEM); 297 return; 298 } 299 300 if (ftype == fun_inner) { 242 static int online_function(fun_node_t *fun) 243 { 244 dev_node_t *dev; 245 246 fibril_rwlock_write_lock(&device_tree.rwlock); 247 248 if (fun->state == FUN_ON_LINE) { 249 fibril_rwlock_write_unlock(&device_tree.rwlock); 250 log_msg(LVL_WARN, "Function %s is already on line.", 251 fun->pathname); 252 return EOK; 253 } 254 255 if (fun->ftype == fun_inner) { 301 256 dev = create_dev_node(); 302 257 if (dev == NULL) { 303 fibril_rwlock_write_unlock(&tree->rwlock); 304 delete_fun_node(fun); 305 async_answer_0(callid, ENOMEM); 306 return; 258 fibril_rwlock_write_unlock(&device_tree.rwlock); 259 return ENOMEM; 307 260 } 308 261 309 insert_dev_node(tree, dev, fun); 310 } 311 312 fibril_rwlock_write_unlock(&tree->rwlock); 262 insert_dev_node(&device_tree, dev, fun); 263 dev_add_ref(dev); 264 } 313 265 314 266 log_msg(LVL_DEBUG, "devman_add_function(fun=\"%s\")", fun->pathname); 315 267 316 devman_receive_match_ids(match_count, &fun->match_ids); 317 318 if (ftype == fun_inner) { 268 if (fun->ftype == fun_inner) { 269 dev = fun->child; 319 270 assert(dev != NULL); 271 272 /* Give one reference over to assign_driver_fibril(). */ 273 dev_add_ref(dev); 320 274 /* 321 275 * Try to find a suitable driver and assign it to the device. We do … … 327 281 fid_t assign_fibril = fibril_create(assign_driver_fibril, dev); 328 282 if (assign_fibril == 0) { 329 /* 330 * Fallback in case we are out of memory. 331 * Probably not needed as we will die soon anyway ;-). 332 */ 333 (void) assign_driver_fibril(fun); 334 } else { 335 fibril_add_ready(assign_fibril); 283 log_msg(LVL_ERROR, "Failed to create fibril for " 284 "assigning driver."); 285 /* XXX Cleanup */ 286 fibril_rwlock_write_unlock(&device_tree.rwlock); 287 return ENOMEM; 288 } 289 fibril_add_ready(assign_fibril); 290 } else { 291 loc_register_tree_function(fun, &device_tree); 292 } 293 294 fibril_rwlock_write_unlock(&device_tree.rwlock); 295 296 return EOK; 297 } 298 299 static int offline_function(fun_node_t *fun) 300 { 301 int rc; 302 303 fibril_rwlock_write_lock(&device_tree.rwlock); 304 305 if (fun->state == FUN_OFF_LINE) { 306 fibril_rwlock_write_unlock(&device_tree.rwlock); 307 log_msg(LVL_WARN, "Function %s is already off line.", 308 fun->pathname); 309 return EOK; 310 } 311 312 if (fun->ftype == fun_inner) { 313 log_msg(LVL_DEBUG, "Offlining inner function %s.", 314 fun->pathname); 315 316 if (fun->child != NULL) { 317 dev_node_t *dev = fun->child; 318 device_state_t dev_state; 319 320 dev_add_ref(dev); 321 dev_state = dev->state; 322 323 fibril_rwlock_write_unlock(&device_tree.rwlock); 324 325 /* If device is owned by driver, ask driver to give it up. */ 326 if (dev_state == DEVICE_USABLE) { 327 rc = driver_dev_remove(&device_tree, dev); 328 if (rc != EOK) { 329 dev_del_ref(dev); 330 return ENOTSUP; 331 } 332 } 333 334 /* Verify that driver removed all functions */ 335 fibril_rwlock_read_lock(&device_tree.rwlock); 336 if (!list_empty(&dev->functions)) { 337 fibril_rwlock_read_unlock(&device_tree.rwlock); 338 dev_del_ref(dev); 339 return EIO; 340 } 341 342 driver_t *driver = dev->drv; 343 fibril_rwlock_read_unlock(&device_tree.rwlock); 344 345 if (driver) 346 detach_driver(&device_tree, dev); 347 348 fibril_rwlock_write_lock(&device_tree.rwlock); 349 remove_dev_node(&device_tree, dev); 350 351 /* Delete ref created when node was inserted */ 352 dev_del_ref(dev); 353 /* Delete ref created by dev_add_ref(dev) above */ 354 dev_del_ref(dev); 336 355 } 337 356 } else { 338 loc_register_tree_function(fun, tree); 357 /* Unregister from location service */ 358 rc = loc_service_unregister(fun->service_id); 359 if (rc != EOK) { 360 fibril_rwlock_write_unlock(&device_tree.rwlock); 361 log_msg(LVL_ERROR, "Failed unregistering tree service."); 362 return EIO; 363 } 364 365 fun->service_id = 0; 366 } 367 368 fun->state = FUN_OFF_LINE; 369 fibril_rwlock_write_unlock(&device_tree.rwlock); 370 371 return EOK; 372 } 373 374 /** Handle function registration. 375 * 376 * Child devices are registered by their parent's device driver. 377 */ 378 static void devman_add_function(ipc_callid_t callid, ipc_call_t *call) 379 { 380 fun_type_t ftype = (fun_type_t) IPC_GET_ARG1(*call); 381 devman_handle_t dev_handle = IPC_GET_ARG2(*call); 382 sysarg_t match_count = IPC_GET_ARG3(*call); 383 dev_tree_t *tree = &device_tree; 384 385 dev_node_t *pdev = find_dev_node(&device_tree, dev_handle); 386 if (pdev == NULL) { 387 async_answer_0(callid, ENOENT); 388 return; 389 } 390 391 if (ftype != fun_inner && ftype != fun_exposed) { 392 /* Unknown function type */ 393 log_msg(LVL_ERROR, 394 "Unknown function type %d provided by driver.", 395 (int) ftype); 396 397 dev_del_ref(pdev); 398 async_answer_0(callid, EINVAL); 399 return; 400 } 401 402 char *fun_name = NULL; 403 int rc = async_data_write_accept((void **)&fun_name, true, 0, 0, 0, 0); 404 if (rc != EOK) { 405 dev_del_ref(pdev); 406 async_answer_0(callid, rc); 407 return; 408 } 409 410 fibril_rwlock_write_lock(&tree->rwlock); 411 412 /* Check device state */ 413 if (pdev->state == DEVICE_REMOVED) { 414 fibril_rwlock_write_unlock(&tree->rwlock); 415 dev_del_ref(pdev); 416 async_answer_0(callid, ENOENT); 417 return; 418 } 419 420 /* Check that function with same name is not there already. */ 421 if (find_fun_node_in_device(tree, pdev, fun_name) != NULL) { 422 fibril_rwlock_write_unlock(&tree->rwlock); 423 dev_del_ref(pdev); 424 async_answer_0(callid, EEXISTS); 425 printf(NAME ": Warning, driver tried to register `%s' twice.\n", 426 fun_name); 427 free(fun_name); 428 return; 429 } 430 431 fun_node_t *fun = create_fun_node(); 432 fun_add_ref(fun); 433 fun->ftype = ftype; 434 435 if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) { 436 fibril_rwlock_write_unlock(&tree->rwlock); 437 dev_del_ref(pdev); 438 delete_fun_node(fun); 439 async_answer_0(callid, ENOMEM); 440 return; 441 } 442 443 fibril_rwlock_write_unlock(&tree->rwlock); 444 dev_del_ref(pdev); 445 446 devman_receive_match_ids(match_count, &fun->match_ids); 447 448 rc = online_function(fun); 449 if (rc != EOK) { 450 /* XXX clean up */ 451 async_answer_0(callid, rc); 452 return; 339 453 } 340 454 … … 356 470 async_answer_0(callid, rc); 357 471 return; 358 } 472 } 359 473 360 474 fun_node_t *fun = find_fun_node(&device_tree, handle); 361 475 if (fun == NULL) { 476 async_answer_0(callid, ENOENT); 477 return; 478 } 479 480 fibril_rwlock_read_lock(&device_tree.rwlock); 481 482 /* Check function state */ 483 if (fun->state == FUN_REMOVED) { 484 fibril_rwlock_read_unlock(&device_tree.rwlock); 362 485 async_answer_0(callid, ENOENT); 363 486 return; … … 375 498 fun->pathname, cat_name); 376 499 500 fibril_rwlock_read_unlock(&device_tree.rwlock); 501 fun_del_ref(fun); 502 377 503 async_answer_0(callid, EOK); 504 } 505 506 /** Online function by driver request. 507 * 508 */ 509 static void devman_drv_fun_online(ipc_callid_t iid, ipc_call_t *icall, 510 driver_t *drv) 511 { 512 fun_node_t *fun; 513 int rc; 514 515 log_msg(LVL_DEBUG, "devman_drv_fun_online()"); 516 517 fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall)); 518 if (fun == NULL) { 519 async_answer_0(iid, ENOENT); 520 return; 521 } 522 523 fibril_rwlock_read_lock(&device_tree.rwlock); 524 if (fun->dev == NULL || fun->dev->drv != drv) { 525 fibril_rwlock_read_unlock(&device_tree.rwlock); 526 fun_del_ref(fun); 527 async_answer_0(iid, ENOENT); 528 return; 529 } 530 fibril_rwlock_read_unlock(&device_tree.rwlock); 531 532 rc = online_function(fun); 533 if (rc != EOK) { 534 fun_del_ref(fun); 535 async_answer_0(iid, (sysarg_t) rc); 536 return; 537 } 538 539 fun_del_ref(fun); 540 541 async_answer_0(iid, (sysarg_t) EOK); 542 } 543 544 545 /** Offline function by driver request. 546 * 547 */ 548 static void devman_drv_fun_offline(ipc_callid_t iid, ipc_call_t *icall, 549 driver_t *drv) 550 { 551 fun_node_t *fun; 552 int rc; 553 554 fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall)); 555 if (fun == NULL) { 556 async_answer_0(iid, ENOENT); 557 return; 558 } 559 560 fibril_rwlock_write_lock(&device_tree.rwlock); 561 if (fun->dev == NULL || fun->dev->drv != drv) { 562 fun_del_ref(fun); 563 async_answer_0(iid, ENOENT); 564 return; 565 } 566 fibril_rwlock_write_unlock(&device_tree.rwlock); 567 568 rc = offline_function(fun); 569 if (rc != EOK) { 570 fun_del_ref(fun); 571 async_answer_0(iid, (sysarg_t) rc); 572 return; 573 } 574 575 fun_del_ref(fun); 576 async_answer_0(iid, (sysarg_t) EOK); 378 577 } 379 578 … … 385 584 int rc; 386 585 586 fun_node_t *fun = find_fun_node(&device_tree, fun_handle); 587 if (fun == NULL) { 588 async_answer_0(callid, ENOENT); 589 return; 590 } 591 387 592 fibril_rwlock_write_lock(&tree->rwlock); 388 593 389 fun_node_t *fun = find_fun_node_no_lock(&device_tree, fun_handle); 390 if (fun == NULL) { 594 log_msg(LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname); 595 596 /* Check function state */ 597 if (fun->state == FUN_REMOVED) { 391 598 fibril_rwlock_write_unlock(&tree->rwlock); 392 599 async_answer_0(callid, ENOENT); … … 394 601 } 395 602 396 log_msg(LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname);397 398 603 if (fun->ftype == fun_inner) { 399 /* Handle possible descendants */ 400 /* TODO */ 401 log_msg(LVL_WARN, "devman_remove_function(): not handling " 402 "descendants\n"); 604 /* This is a surprise removal. Handle possible descendants */ 605 if (fun->child != NULL) { 606 dev_node_t *dev = fun->child; 607 device_state_t dev_state; 608 int gone_rc; 609 610 dev_add_ref(dev); 611 dev_state = dev->state; 612 613 fibril_rwlock_write_unlock(&device_tree.rwlock); 614 615 /* If device is owned by driver, inform driver it is gone. */ 616 if (dev_state == DEVICE_USABLE) 617 gone_rc = driver_dev_gone(&device_tree, dev); 618 else 619 gone_rc = EOK; 620 621 fibril_rwlock_read_lock(&device_tree.rwlock); 622 623 /* Verify that driver succeeded and removed all functions */ 624 if (gone_rc != EOK || !list_empty(&dev->functions)) { 625 log_msg(LVL_ERROR, "Driver did not remove " 626 "functions for device that is gone. " 627 "Device node is now defunct."); 628 629 /* 630 * Not much we can do but mark the device 631 * node as having invalid state. This 632 * is a driver bug. 633 */ 634 dev->state = DEVICE_INVALID; 635 fibril_rwlock_read_unlock(&device_tree.rwlock); 636 dev_del_ref(dev); 637 return; 638 } 639 640 driver_t *driver = dev->drv; 641 fibril_rwlock_read_unlock(&device_tree.rwlock); 642 643 if (driver) 644 detach_driver(&device_tree, dev); 645 646 fibril_rwlock_write_lock(&device_tree.rwlock); 647 remove_dev_node(&device_tree, dev); 648 649 /* Delete ref created when node was inserted */ 650 dev_del_ref(dev); 651 /* Delete ref created by dev_add_ref(dev) above */ 652 dev_del_ref(dev); 653 } 403 654 } else { 404 /* Unregister from location service */ 405 rc = loc_service_unregister(fun->service_id); 406 if (rc != EOK) { 407 log_msg(LVL_ERROR, "Failed unregistering tree service."); 408 fibril_rwlock_write_unlock(&tree->rwlock); 409 async_answer_0(callid, EIO); 410 return; 655 if (fun->service_id != 0) { 656 /* Unregister from location service */ 657 rc = loc_service_unregister(fun->service_id); 658 if (rc != EOK) { 659 log_msg(LVL_ERROR, "Failed unregistering tree " 660 "service."); 661 fibril_rwlock_write_unlock(&tree->rwlock); 662 fun_del_ref(fun); 663 async_answer_0(callid, EIO); 664 return; 665 } 411 666 } 412 667 } … … 414 669 remove_fun_node(&device_tree, fun); 415 670 fibril_rwlock_write_unlock(&tree->rwlock); 416 delete_fun_node(fun); 671 672 /* Delete ref added when inserting function into tree */ 673 fun_del_ref(fun); 674 /* Delete ref added above when looking up function */ 675 fun_del_ref(fun); 417 676 418 677 log_msg(LVL_DEBUG, "devman_remove_function() succeeded."); … … 485 744 devman_add_function_to_cat(callid, &call); 486 745 break; 746 case DEVMAN_DRV_FUN_ONLINE: 747 devman_drv_fun_online(callid, &call, driver); 748 break; 749 case DEVMAN_DRV_FUN_OFFLINE: 750 devman_drv_fun_offline(callid, &call, driver); 751 break; 487 752 case DEVMAN_REMOVE_FUNCTION: 488 753 devman_remove_function(callid, &call); 489 754 break; 490 755 default: 491 async_answer_0(callid, EINVAL); 756 async_answer_0(callid, EINVAL); 492 757 break; 493 758 } … … 500 765 { 501 766 char *pathname; 767 devman_handle_t handle; 502 768 503 769 int rc = async_data_write_accept((void **) &pathname, true, 0, 0, 0, 0); … … 516 782 } 517 783 518 async_answer_1(iid, EOK, fun->handle); 784 fibril_rwlock_read_lock(&device_tree.rwlock); 785 786 /* Check function state */ 787 if (fun->state == FUN_REMOVED) { 788 fibril_rwlock_read_unlock(&device_tree.rwlock); 789 async_answer_0(iid, ENOENT); 790 return; 791 } 792 handle = fun->handle; 793 794 fibril_rwlock_read_unlock(&device_tree.rwlock); 795 796 /* Delete reference created above by find_fun_node_by_path() */ 797 fun_del_ref(fun); 798 799 async_answer_1(iid, EOK, handle); 519 800 } 520 801 … … 534 815 if (!async_data_read_receive(&data_callid, &data_len)) { 535 816 async_answer_0(iid, EINVAL); 817 fun_del_ref(fun); 536 818 return; 537 819 } … … 541 823 async_answer_0(data_callid, ENOMEM); 542 824 async_answer_0(iid, ENOMEM); 825 fun_del_ref(fun); 826 return; 827 } 828 829 fibril_rwlock_read_lock(&device_tree.rwlock); 830 831 /* Check function state */ 832 if (fun->state == FUN_REMOVED) { 833 fibril_rwlock_read_unlock(&device_tree.rwlock); 834 free(buffer); 835 836 async_answer_0(data_callid, ENOENT); 837 async_answer_0(iid, ENOENT); 838 fun_del_ref(fun); 543 839 return; 544 840 } … … 552 848 async_answer_0(iid, EOK); 553 849 850 fibril_rwlock_read_unlock(&device_tree.rwlock); 851 fun_del_ref(fun); 554 852 free(buffer); 555 853 } … … 571 869 if (!async_data_read_receive(&data_callid, &data_len)) { 572 870 async_answer_0(iid, EINVAL); 871 fun_del_ref(fun); 573 872 return; 574 873 } … … 578 877 async_answer_0(data_callid, ENOMEM); 579 878 async_answer_0(iid, ENOMEM); 580 return; 581 } 582 879 fun_del_ref(fun); 880 return; 881 } 882 883 fibril_rwlock_read_lock(&device_tree.rwlock); 884 885 /* Check function state */ 886 if (fun->state == FUN_REMOVED) { 887 fibril_rwlock_read_unlock(&device_tree.rwlock); 888 free(buffer); 889 890 async_answer_0(data_callid, ENOENT); 891 async_answer_0(iid, ENOENT); 892 fun_del_ref(fun); 893 return; 894 } 895 583 896 size_t sent_length = str_size(fun->pathname); 584 897 if (sent_length > data_len) { … … 589 902 async_answer_0(iid, EOK); 590 903 904 fibril_rwlock_read_unlock(&device_tree.rwlock); 905 fun_del_ref(fun); 591 906 free(buffer); 592 907 } … … 609 924 dev_node_t *dev = find_dev_node_no_lock(&device_tree, 610 925 IPC_GET_ARG1(*icall)); 611 if (dev == NULL ) {926 if (dev == NULL || dev->state == DEVICE_REMOVED) { 612 927 fibril_rwlock_read_unlock(&device_tree.rwlock); 613 928 async_answer_0(callid, ENOENT); … … 648 963 fibril_rwlock_read_lock(&device_tree.rwlock); 649 964 965 fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall)); 966 if (fun == NULL || fun->state == FUN_REMOVED) { 967 fibril_rwlock_read_unlock(&device_tree.rwlock); 968 async_answer_0(iid, ENOENT); 969 return; 970 } 971 972 if (fun->child == NULL) { 973 fibril_rwlock_read_unlock(&device_tree.rwlock); 974 async_answer_0(iid, ENOENT); 975 return; 976 } 977 978 async_answer_1(iid, EOK, fun->child->handle); 979 980 fibril_rwlock_read_unlock(&device_tree.rwlock); 981 } 982 983 /** Online function. 984 * 985 * Send a request to online a function to the responsible driver. 986 * The driver may offline other functions if necessary (i.e. if the state 987 * of this function is linked to state of another function somehow). 988 */ 989 static void devman_fun_online(ipc_callid_t iid, ipc_call_t *icall) 990 { 991 fun_node_t *fun; 992 int rc; 993 650 994 fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall)); 651 995 if (fun == NULL) { 652 fibril_rwlock_read_unlock(&device_tree.rwlock); 653 async_answer_0(iid, ENOENT); 654 return; 655 } 656 657 if (fun->child == NULL) { 658 fibril_rwlock_read_unlock(&device_tree.rwlock); 659 async_answer_0(iid, ENOENT); 660 return; 661 } 662 663 async_answer_1(iid, EOK, fun->child->handle); 664 665 fibril_rwlock_read_unlock(&device_tree.rwlock); 996 async_answer_0(iid, ENOENT); 997 return; 998 } 999 1000 rc = driver_fun_online(&device_tree, fun); 1001 fun_del_ref(fun); 1002 1003 async_answer_0(iid, (sysarg_t) rc); 1004 } 1005 1006 /** Offline function. 1007 * 1008 * Send a request to offline a function to the responsible driver. As 1009 * a result the subtree rooted at that function should be cleanly 1010 * detatched. The driver may offline other functions if necessary 1011 * (i.e. if the state of this function is linked to state of another 1012 * function somehow). 1013 */ 1014 static void devman_fun_offline(ipc_callid_t iid, ipc_call_t *icall) 1015 { 1016 fun_node_t *fun; 1017 int rc; 1018 1019 fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall)); 1020 if (fun == NULL) { 1021 async_answer_0(iid, ENOENT); 1022 return; 1023 } 1024 1025 rc = driver_fun_offline(&device_tree, fun); 1026 fun_del_ref(fun); 1027 1028 async_answer_0(iid, (sysarg_t) rc); 666 1029 } 667 1030 … … 678 1041 } 679 1042 1043 fibril_rwlock_read_lock(&device_tree.rwlock); 1044 1045 /* Check function state */ 1046 if (fun->state == FUN_REMOVED) { 1047 fibril_rwlock_read_unlock(&device_tree.rwlock); 1048 async_answer_0(iid, ENOENT); 1049 return; 1050 } 1051 680 1052 async_answer_1(iid, EOK, fun->handle); 1053 fibril_rwlock_read_unlock(&device_tree.rwlock); 1054 fun_del_ref(fun); 681 1055 } 682 1056 … … 710 1084 devman_fun_get_path(callid, &call); 711 1085 break; 1086 case DEVMAN_FUN_ONLINE: 1087 devman_fun_online(callid, &call); 1088 break; 1089 case DEVMAN_FUN_OFFLINE: 1090 devman_fun_offline(callid, &call); 1091 break; 712 1092 case DEVMAN_FUN_SID_TO_HANDLE: 713 1093 devman_fun_sid_to_handle(callid, &call); … … 730 1110 if (fun == NULL) 731 1111 dev = find_dev_node(&device_tree, handle); 732 else 1112 else { 1113 fibril_rwlock_read_lock(&device_tree.rwlock); 733 1114 dev = fun->dev; 1115 if (dev != NULL) 1116 dev_add_ref(dev); 1117 fibril_rwlock_read_unlock(&device_tree.rwlock); 1118 } 734 1119 735 1120 /* … … 743 1128 "function with handle %" PRIun " was found.", handle); 744 1129 async_answer_0(iid, ENOENT); 745 return;1130 goto cleanup; 746 1131 } 747 1132 … … 751 1136 handle); 752 1137 async_answer_0(iid, ENOENT); 753 return;1138 goto cleanup; 754 1139 } 755 1140 756 1141 driver_t *driver = NULL; 1142 1143 fibril_rwlock_read_lock(&device_tree.rwlock); 757 1144 758 1145 if (drv_to_parent) { … … 769 1156 } 770 1157 1158 fibril_rwlock_read_unlock(&device_tree.rwlock); 1159 771 1160 if (driver == NULL) { 772 1161 log_msg(LVL_ERROR, "IPC forwarding refused - " \ 773 1162 "the device %" PRIun " is not in usable state.", handle); 774 1163 async_answer_0(iid, ENOENT); 775 return;1164 goto cleanup; 776 1165 } 777 1166 … … 786 1175 "Could not forward to driver `%s'.", driver->name); 787 1176 async_answer_0(iid, EINVAL); 788 return;1177 goto cleanup; 789 1178 } 790 1179 … … 802 1191 async_forward_fast(iid, exch, method, fwd_h, 0, IPC_FF_NONE); 803 1192 async_exchange_end(exch); 1193 1194 cleanup: 1195 if (dev != NULL) 1196 dev_del_ref(dev); 1197 if (fun != NULL) 1198 fun_del_ref(fun); 804 1199 } 805 1200 … … 811 1206 fun_node_t *fun; 812 1207 dev_node_t *dev; 1208 devman_handle_t handle; 1209 driver_t *driver; 813 1210 814 1211 fun = find_loc_tree_function(&device_tree, service_id); 815 1212 816 if (fun == NULL || fun->dev->drv == NULL) { 1213 fibril_rwlock_read_lock(&device_tree.rwlock); 1214 1215 if (fun == NULL || fun->dev == NULL || fun->dev->drv == NULL) { 817 1216 log_msg(LVL_WARN, "devman_connection_loc(): function " 818 1217 "not found.\n"); 1218 fibril_rwlock_read_unlock(&device_tree.rwlock); 819 1219 async_answer_0(iid, ENOENT); 820 1220 return; … … 822 1222 823 1223 dev = fun->dev; 824 825 async_exch_t *exch = async_exchange_begin(dev->drv->sess); 826 async_forward_fast(iid, exch, DRIVER_CLIENT, fun->handle, 0, 1224 driver = dev->drv; 1225 handle = fun->handle; 1226 1227 fibril_rwlock_read_unlock(&device_tree.rwlock); 1228 1229 async_exch_t *exch = async_exchange_begin(driver->sess); 1230 async_forward_fast(iid, exch, DRIVER_CLIENT, handle, 0, 827 1231 IPC_FF_NONE); 828 1232 async_exchange_end(exch); … … 830 1234 log_msg(LVL_DEBUG, 831 1235 "Forwarding loc service request for `%s' function to driver `%s'.", 832 fun->pathname, dev->drv->name); 1236 fun->pathname, driver->name); 1237 1238 fun_del_ref(fun); 833 1239 } 834 1240 -
uspace/srv/fs/ext2fs/ext2fs_ops.c
rbb74dabe rc05642d 112 112 static bool ext2fs_is_directory(fs_node_t *); 113 113 static bool ext2fs_is_file(fs_node_t *node); 114 static service_id_t ext2fs_ device_get(fs_node_t *node);114 static service_id_t ext2fs_service_get(fs_node_t *node); 115 115 116 116 /* … … 557 557 } 558 558 559 service_id_t ext2fs_ device_get(fs_node_t *fn)559 service_id_t ext2fs_service_get(fs_node_t *fn) 560 560 { 561 561 EXT2FS_DBG(""); … … 581 581 .is_directory = ext2fs_is_directory, 582 582 .is_file = ext2fs_is_file, 583 . device_get = ext2fs_device_get583 .service_get = ext2fs_service_get 584 584 }; 585 585 -
uspace/srv/fs/fat/Makefile
rbb74dabe rc05642d 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
rbb74dabe rc05642d 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 * -
uspace/srv/fs/fat/fat.h
rbb74dabe rc05642d 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) ((a) < (b) ? (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 { -
uspace/srv/fs/fat/fat_dentry.c
rbb74dabe rc05642d 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
rbb74dabe rc05642d 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
rbb74dabe rc05642d 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 … … 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 75 int 84 76 fat_cluster_walk(fat_bs_t *bs, service_id_t service_id, 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;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, service_id, 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 … … 178 162 if (rc != EOK) 179 163 return rc; 180 164 181 165 /* 182 166 * Update the "current" cluster cache. … … 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. … … 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)); … … 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)) { … … 304 289 * @return EOK or a negative error code. 305 290 */ 291 static int 292 fat_get_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 293 fat_cluster_t clst, fat_cluster_t *value) 294 { 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); 306 if (rc != EOK) 307 return rc; 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 347 rc = block_put(b); 348 349 return rc; 350 } 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 */ 306 425 int 307 426 fat_get_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 308 427 fat_cluster_t clst, fat_cluster_t *value) 309 428 { 310 block_t *b; 311 fat_cluster_t *cp; 312 int rc; 313 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 443 /** Set cluster in one instance of FAT. 444 * 445 * @param bs Buffer holding the boot sector for the file system. 446 * @param service_id Service ID for the file system. 447 * @param fatno Number of the FAT instance where to make the change. 448 * @param clst Cluster which is to be set. 449 * @param value Value to set the cluster with. 450 * 451 * @return EOK on success or a negative error code. 452 */ 453 static int 454 fat_set_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 455 fat_cluster_t clst, fat_cluster_t value) 456 { 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 314 466 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno + 315 (clst * sizeof(fat_cluster_t))/ BPS(bs), BLOCK_FLAGS_NONE);467 offset / BPS(bs), BLOCK_FLAGS_NONE); 316 468 if (rc != EOK) 317 469 return rc; 318 cp = (fat_cluster_t *)b->data + 319 clst % (BPS(bs) / sizeof(fat_cluster_t)); 320 *value = uint16_t_le2host(*cp); 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 */ 321 526 rc = block_put(b); 322 527 528 return rc; 529 } 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 323 598 return rc; 324 599 } … … 338 613 fat_cluster_t clst, fat_cluster_t value) 339 614 { 340 block_t *b;341 fat_cluster_t *cp;342 615 int rc; 343 616 344 617 assert(fatno < FATCNT(bs)); 345 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno + 346 (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE); 347 if (rc != EOK) 348 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 */ 353 rc = block_put(b); 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 354 626 return rc; 355 627 } … … 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 648 rc = fat_set_cluster(bs, service_id, fatno, lifo[c], 376 c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);649 c == 0 ? clst_last1 : lifo[c - 1]); 377 650 if (rc != EOK) 378 651 return rc; … … 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, service_id, 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 service_id, 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, service_id, 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 } … … 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); 752 while (firstc < FAT_CLST_LAST1(bs)) { 753 assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad); 754 517 755 rc = fat_get_cluster(bs, service_id, FAT1, firstc, &nextc); 518 756 if (rc != EOK) 519 757 return rc; 520 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 758 759 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) { 521 760 rc = fat_set_cluster(bs, service_id, fatno, firstc, 522 761 FAT_CLST_RES0); … … 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 { … … 559 797 } else { 560 798 rc = fat_cluster_walk(bs, service_id, nodep->firstc, 561 &lastc, NULL, (uint 16_t) -1);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->service_id, 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 { 830 fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs); 592 831 int rc; 593 832 service_id_t service_id = nodep->idx->service_id; … … 616 855 617 856 /* Terminate the cluster chain in all copies of FAT. */ 618 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {857 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) { 619 858 rc = fat_set_cluster(bs, service_id, fatno, lcl, 620 FAT_CLST_LAST1);859 clst_last1); 621 860 if (rc != EOK) 622 861 return rc; … … 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++) { 945 for (fat_no = 0; fat_no < FATCNT(bs); fat_no++) { 709 946 rc = fat_get_cluster(bs, service_id, fat_no, 0, &e0); 710 947 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
rbb74dabe rc05642d 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)108 #define fat_clusters_get(numc, bs, sid, fc) \ 109 fat_cluster_walk((bs), (sid), (fc), NULL, (numc), (uint32_t) -1) 63 110 extern int fat_cluster_walk(struct fat_bs *, service_id_t, fat_cluster_t, 64 fat_cluster_t *, uint 16_t *, uint16_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 *, -
uspace/srv/fs/fat/fat_idx.c
rbb74dabe rc05642d 116 116 #define UPH_BUCKETS (1 << UPH_BUCKETS_LOG) 117 117 118 #define UPH_ DH_KEY 0118 #define UPH_SID_KEY 0 119 119 #define UPH_PFC_KEY 1 120 120 #define UPH_PDI_KEY 2 … … 122 122 static hash_index_t pos_hash(unsigned long key[]) 123 123 { 124 service_id_t service_id = (service_id_t)key[UPH_ DH_KEY];124 service_id_t service_id = (service_id_t)key[UPH_SID_KEY]; 125 125 fat_cluster_t pfc = (fat_cluster_t)key[UPH_PFC_KEY]; 126 126 unsigned pdi = (unsigned)key[UPH_PDI_KEY]; … … 150 150 static int pos_compare(unsigned long key[], hash_count_t keys, link_t *item) 151 151 { 152 service_id_t service_id = (service_id_t)key[UPH_ DH_KEY];152 service_id_t service_id = (service_id_t)key[UPH_SID_KEY]; 153 153 fat_cluster_t pfc; 154 154 unsigned pdi; … … 190 190 #define UIH_BUCKETS (1 << UIH_BUCKETS_LOG) 191 191 192 #define UIH_ DH_KEY 0192 #define UIH_SID_KEY 0 193 193 #define UIH_INDEX_KEY 1 194 194 195 195 static hash_index_t idx_hash(unsigned long key[]) 196 196 { 197 service_id_t service_id = (service_id_t)key[UIH_ DH_KEY];197 service_id_t service_id = (service_id_t)key[UIH_SID_KEY]; 198 198 fs_index_t index = (fs_index_t)key[UIH_INDEX_KEY]; 199 199 … … 209 209 static int idx_compare(unsigned long key[], hash_count_t keys, link_t *item) 210 210 { 211 service_id_t service_id = (service_id_t)key[UIH_ DH_KEY];211 service_id_t service_id = (service_id_t)key[UIH_SID_KEY]; 212 212 fs_index_t index; 213 213 fat_idx_t *fidx = list_get_instance(item, fat_idx_t, uih_link); … … 402 402 403 403 unsigned long ikey[] = { 404 [UIH_ DH_KEY] = service_id,404 [UIH_SID_KEY] = service_id, 405 405 [UIH_INDEX_KEY] = fidx->index, 406 406 }; … … 420 420 link_t *l; 421 421 unsigned long pkey[] = { 422 [UPH_ DH_KEY] = service_id,422 [UPH_SID_KEY] = service_id, 423 423 [UPH_PFC_KEY] = pfc, 424 424 [UPH_PDI_KEY] = pdi, … … 439 439 440 440 unsigned long ikey[] = { 441 [UIH_ DH_KEY] = service_id,441 [UIH_SID_KEY] = service_id, 442 442 [UIH_INDEX_KEY] = fidx->index, 443 443 }; … … 458 458 { 459 459 unsigned long pkey[] = { 460 [UPH_ DH_KEY] = idx->service_id,460 [UPH_SID_KEY] = idx->service_id, 461 461 [UPH_PFC_KEY] = idx->pfc, 462 462 [UPH_PDI_KEY] = idx->pdi, … … 471 471 { 472 472 unsigned long pkey[] = { 473 [UPH_ DH_KEY] = idx->service_id,473 [UPH_SID_KEY] = idx->service_id, 474 474 [UPH_PFC_KEY] = idx->pfc, 475 475 [UPH_PDI_KEY] = idx->pdi, … … 487 487 link_t *l; 488 488 unsigned long ikey[] = { 489 [UIH_ DH_KEY] = service_id,489 [UIH_SID_KEY] = service_id, 490 490 [UIH_INDEX_KEY] = index, 491 491 }; … … 509 509 { 510 510 unsigned long ikey[] = { 511 [UIH_ DH_KEY] = idx->service_id,511 [UIH_SID_KEY] = idx->service_id, 512 512 [UIH_INDEX_KEY] = idx->index, 513 513 }; … … 571 571 { 572 572 unsigned long ikey[] = { 573 [UIH_ DH_KEY] = service_id573 [UIH_SID_KEY] = service_id 574 574 }; 575 575 unsigned long pkey[] = { 576 [UPH_ DH_KEY] = service_id576 [UPH_SID_KEY] = service_id 577 577 }; 578 578 -
uspace/srv/fs/fat/fat_ops.c
rbb74dabe rc05642d 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> … … 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) … … 87 90 static bool fat_is_directory(fs_node_t *); 88 91 static bool fat_is_file(fs_node_t *node); 89 static service_id_t fat_ device_get(fs_node_t *node);92 static service_id_t fat_service_get(fs_node_t *node); 90 93 91 94 /* … … 104 107 node->dirty = false; 105 108 node->lastc_cached_valid = false; 106 node->lastc_cached_value = FAT_CLST_LAST1;109 node->lastc_cached_value = 0; 107 110 node->currc_cached_valid = false; 108 111 node->currc_cached_bn = 0; 109 node->currc_cached_value = FAT_CLST_LAST1;112 node->currc_cached_value = 0; 110 113 } 111 114 … … 116 119 fat_dentry_t *d; 117 120 int rc; 118 121 119 122 assert(node->dirty); 120 123 121 124 bs = block_bb_get(node->idx->service_id); 122 125 123 126 /* Read the block that contains the dentry of interest. */ 124 127 rc = _fat_block_get(&b, bs, node->idx->service_id, node->idx->pfc, … … 136 139 d->attr = FAT_ATTR_SUBDIR; 137 140 } 138 141 139 142 /* TODO: update other fields? (e.g time fields) */ 140 143 141 144 b->dirty = true; /* need to sync block */ 142 145 rc = block_put(b); … … 255 258 fn->data = nodep; 256 259 nodep->bp = fn; 257 260 258 261 *nodepp = nodep; 259 262 return EOK; … … 291 294 * We must instantiate the node from the file system. 292 295 */ 293 296 294 297 assert(idxp->pfc); 295 298 … … 309 312 310 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 311 320 if (d->attr & FAT_ATTR_SUBDIR) { 312 /* 321 /* 313 322 * The only directory which does not have this bit set is the 314 323 * root directory itself. The root directory node is handled … … 316 325 */ 317 326 nodep->type = FAT_DIRECTORY; 327 318 328 /* 319 329 * Unfortunately, the 'size' field of the FAT dentry is not … … 321 331 * size of the directory by walking the FAT. 322 332 */ 323 uint 16_t clusters;333 uint32_t clusters; 324 334 rc = fat_clusters_get(&clusters, bs, idxp->service_id, 325 uint16_t_le2host(d->firstc));335 nodep->firstc); 326 336 if (rc != EOK) { 327 337 (void) block_put(b); … … 334 344 nodep->size = uint32_t_le2host(d->size); 335 345 } 336 nodep->firstc = uint16_t_le2host(d->firstc); 346 337 347 nodep->lnkcnt = 1; 338 348 nodep->refcnt = 1; … … 363 373 int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 364 374 { 365 fat_bs_t *bs;366 375 fat_node_t *parentp = FAT_NODE(pfn); 367 char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; 368 unsigned i, j; 369 unsigned blocks; 376 char name[FAT_LFN_NAME_SIZE]; 370 377 fat_dentry_t *d; 371 378 service_id_t service_id; 372 block_t *b;373 379 int rc; 374 380 … … 376 382 service_id = parentp->idx->service_id; 377 383 fibril_mutex_unlock(&parentp->idx->lock); 378 379 bs = block_bb_get(service_id); 380 blocks = parentp->size / BPS(bs); 381 for (i = 0; i < blocks; i++) { 382 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 383 if (rc != EOK) 384 return rc; 385 for (j = 0; j < DPS(bs); j++) { 386 d = ((fat_dentry_t *)b->data) + j; 387 switch (fat_classify_dentry(d)) { 388 case FAT_DENTRY_SKIP: 389 case FAT_DENTRY_FREE: 390 continue; 391 case FAT_DENTRY_LAST: 392 /* miss */ 393 rc = block_put(b); 394 *rfn = NULL; 395 return rc; 396 default: 397 case FAT_DENTRY_VALID: 398 fat_dentry_name_get(d, name); 399 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; 400 405 } 401 if (fat_dentry_namecmp(name, component) == 0) { 402 /* hit */ 403 fat_node_t *nodep; 404 fat_idx_t *idx = fat_idx_get_by_pos(service_id, 405 parentp->firstc, i * DPS(bs) + j); 406 if (!idx) { 407 /* 408 * Can happen if memory is low or if we 409 * run out of 32-bit indices. 410 */ 411 rc = block_put(b); 412 return (rc == EOK) ? ENOMEM : rc; 413 } 414 rc = fat_node_get_core(&nodep, idx); 415 fibril_mutex_unlock(&idx->lock); 416 if (rc != EOK) { 417 (void) block_put(b); 418 return rc; 419 } 420 *rfn = FS_NODE(nodep); 421 rc = block_put(b); 422 if (rc != EOK) 423 (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); 424 410 return rc; 425 411 } 426 } 427 rc = block_put(b); 428 if (rc != EOK) 412 *rfn = FS_NODE(nodep); 413 rc = fat_directory_close(&di); 414 if (rc != EOK) 415 (void) fat_node_put(*rfn); 429 416 return rc; 430 } 431 417 } else { 418 rc = fat_directory_next(&di); 419 if (rc != EOK) 420 break; 421 } 422 } 423 (void) fat_directory_close(&di); 432 424 *rfn = NULL; 433 425 return EOK; … … 591 583 fat_bs_t *bs; 592 584 block_t *b; 593 unsigned i, j; 594 unsigned blocks; 595 fat_cluster_t mcl, lcl; 585 fat_directory_t di; 586 fat_dentry_t de; 596 587 int rc; 597 588 … … 607 598 fibril_mutex_unlock(&childp->lock); 608 599 609 if (!fat_dentry_name_verify(name)) { 610 /* 611 * Attempt to create unsupported name. 612 */ 600 if (!fat_valid_name(name)) 613 601 return ENOTSUP; 614 } 615 616 /* 617 * Get us an unused parent node's dentry or grow the parent and allocate 618 * a new one. 619 */ 620 602 621 603 fibril_mutex_lock(&parentp->idx->lock); 622 604 bs = block_bb_get(parentp->idx->service_id); 623 624 blocks = parentp->size / BPS(bs); 625 626 for (i = 0; i < blocks; i++) { 627 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 628 if (rc != EOK) { 629 fibril_mutex_unlock(&parentp->idx->lock); 630 return rc; 631 } 632 for (j = 0; j < DPS(bs); j++) { 633 d = ((fat_dentry_t *)b->data) + j; 634 switch (fat_classify_dentry(d)) { 635 case FAT_DENTRY_SKIP: 636 case FAT_DENTRY_VALID: 637 /* skipping used and meta entries */ 638 continue; 639 case FAT_DENTRY_FREE: 640 case FAT_DENTRY_LAST: 641 /* found an empty slot */ 642 goto hit; 643 } 644 } 645 rc = block_put(b); 646 if (rc != EOK) { 647 fibril_mutex_unlock(&parentp->idx->lock); 648 return rc; 649 } 650 } 651 j = 0; 652 653 /* 654 * We need to grow the parent in order to create a new unused dentry. 655 */ 656 if (parentp->firstc == FAT_CLST_ROOT) { 657 /* Can't grow the root directory. */ 658 fibril_mutex_unlock(&parentp->idx->lock); 659 return ENOSPC; 660 } 661 rc = fat_alloc_clusters(bs, parentp->idx->service_id, 1, &mcl, &lcl); 605 rc = fat_directory_open(parentp, &di); 662 606 if (rc != EOK) { 663 607 fibril_mutex_unlock(&parentp->idx->lock); 664 608 return rc; 665 609 } 666 rc = fat_zero_cluster(bs, parentp->idx->service_id, mcl); 667 if (rc != EOK) { 668 (void) fat_free_clusters(bs, parentp->idx->service_id, mcl); 669 fibril_mutex_unlock(&parentp->idx->lock); 670 return rc; 671 } 672 rc = fat_append_clusters(bs, parentp, mcl, lcl); 673 if (rc != EOK) { 674 (void) fat_free_clusters(bs, parentp->idx->service_id, mcl); 675 fibril_mutex_unlock(&parentp->idx->lock); 676 return rc; 677 } 678 parentp->size += BPS(bs) * SPC(bs); 679 parentp->dirty = true; /* need to sync node */ 680 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 681 if (rc != EOK) { 682 fibril_mutex_unlock(&parentp->idx->lock); 683 return rc; 684 } 685 d = (fat_dentry_t *)b->data; 686 687 hit: 610 688 611 /* 689 612 * At this point we only establish the link between the parent and the … … 692 615 * dentry data is kept in the child node structure. 693 616 */ 694 memset(d, 0, sizeof(fat_dentry_t)); 695 fat_dentry_name_set(d, name); 696 b->dirty = true; /* need to sync block */ 697 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 698 631 fibril_mutex_unlock(&parentp->idx->lock); 699 if (rc != EOK)700 return rc;701 632 702 633 fibril_mutex_lock(&childp->idx->lock); 703 634 704 635 if (childp->type == FAT_DIRECTORY) { 705 636 /* … … 720 651 d = (fat_dentry_t *) b->data; 721 652 if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) || 722 ( str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) {653 (bcmp(d->name, FAT_NAME_DOT, FAT_NAME_LEN)) == 0) { 723 654 memset(d, 0, sizeof(fat_dentry_t)); 724 655 memcpy(d->name, FAT_NAME_DOT, FAT_NAME_LEN); … … 730 661 d++; 731 662 if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) || 732 ( str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) {663 (bcmp(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN) == 0)) { 733 664 memset(d, 0, sizeof(fat_dentry_t)); 734 665 memcpy(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN); 735 666 memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN); 736 667 d->attr = FAT_ATTR_SUBDIR; 737 d->firstc = (parentp->firstc == FAT_ CLST_ROOT) ?738 host2uint16_t_le(FAT_CLST_R ES0) :668 d->firstc = (parentp->firstc == FAT_ROOT_CLST(bs)) ? 669 host2uint16_t_le(FAT_CLST_ROOTPAR) : 739 670 host2uint16_t_le(parentp->firstc); 740 671 /* TODO: initialize also the date/time members. */ … … 750 681 751 682 childp->idx->pfc = parentp->firstc; 752 childp->idx->pdi = i * DPS(bs) + j;683 childp->idx->pdi = di.pos; /* di.pos holds absolute position of SFN entry */ 753 684 fibril_mutex_unlock(&childp->idx->lock); 754 685 … … 770 701 fat_node_t *parentp = FAT_NODE(pfn); 771 702 fat_node_t *childp = FAT_NODE(cfn); 772 fat_bs_t *bs;773 fat_dentry_t *d;774 block_t *b;775 703 bool has_children; 776 704 int rc; … … 778 706 if (!parentp) 779 707 return EBUSY; 780 708 781 709 rc = fat_has_children(&has_children, cfn); 782 710 if (rc != EOK) … … 789 717 assert(childp->lnkcnt == 1); 790 718 fibril_mutex_lock(&childp->idx->lock); 791 bs = block_bb_get(childp->idx->service_id); 792 793 rc = _fat_block_get(&b, bs, childp->idx->service_id, childp->idx->pfc, 794 NULL, (childp->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs), 795 BLOCK_FLAGS_NONE); 796 if (rc != EOK) 719 720 fat_directory_t di; 721 rc = fat_directory_open(parentp, &di); 722 if (rc != EOK) 797 723 goto error; 798 d = (fat_dentry_t *)b->data + 799 (childp->idx->pdi % (BPS(bs) / sizeof(fat_dentry_t))); 800 /* mark the dentry as not-currently-used */ 801 d->name[0] = FAT_DENTRY_ERASED; 802 b->dirty = true; /* need to sync block */ 803 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); 804 731 if (rc != EOK) 805 732 goto error; … … 820 747 821 748 error: 822 fibril_mutex_unlock(&parentp->idx->lock); 749 (void) fat_directory_close(&di); 750 fibril_mutex_unlock(&childp->idx->lock); 823 751 fibril_mutex_unlock(&childp->lock); 824 fibril_mutex_unlock(& childp->idx->lock);752 fibril_mutex_unlock(&parentp->lock); 825 753 return rc; 826 754 } … … 839 767 return EOK; 840 768 } 841 769 842 770 fibril_mutex_lock(&nodep->idx->lock); 843 771 bs = block_bb_get(nodep->idx->service_id); … … 847 775 for (i = 0; i < blocks; i++) { 848 776 fat_dentry_t *d; 849 777 850 778 rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE); 851 779 if (rc != EOK) { … … 875 803 if (rc != EOK) { 876 804 fibril_mutex_unlock(&nodep->idx->lock); 877 return rc; 805 return rc; 878 806 } 879 807 } … … 910 838 } 911 839 912 service_id_t fat_ device_get(fs_node_t *node)840 service_id_t fat_service_get(fs_node_t *node) 913 841 { 914 842 return 0; … … 932 860 .is_directory = fat_is_directory, 933 861 .is_file = fat_is_file, 934 . device_get = fat_device_get862 .service_get = fat_service_get 935 863 }; 936 864 … … 946 874 fat_bs_t *bs; 947 875 int rc; 948 876 949 877 /* Check for option enabling write through. */ 950 878 if (str_cmp(opts, "wtcache") == 0) … … 1003 931 return ENOMEM; 1004 932 } 933 1005 934 fs_node_initialize(rfn); 1006 935 fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t)); … … 1027 956 1028 957 rootp->type = FAT_DIRECTORY; 1029 rootp->firstc = FAT_ CLST_ROOT;958 rootp->firstc = FAT_ROOT_CLST(bs); 1030 959 rootp->refcnt = 1; 1031 960 rootp->lnkcnt = 0; /* FS root is not linked */ 1032 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 1033 977 rootp->idx = ridxp; 1034 978 ridxp->nodep = rootp; 1035 979 rootp->bp = rfn; 1036 980 rfn->data = rootp; 1037 981 1038 982 fibril_mutex_unlock(&ridxp->lock); 1039 983 … … 1064 1008 return EBUSY; 1065 1009 } 1066 1010 1067 1011 /* 1068 1012 * Put the root node and force it to the FAT free node list. … … 1141 1085 } 1142 1086 } else { 1143 unsigned bnum;1144 1087 aoff64_t spos = pos; 1145 char name[FAT_ NAME_LEN + 1 + FAT_EXT_LEN + 1];1088 char name[FAT_LFN_NAME_SIZE]; 1146 1089 fat_dentry_t *d; 1147 1090 … … 1150 1093 assert(BPS(bs) % sizeof(fat_dentry_t) == 0); 1151 1094 1152 /* 1153 * Our strategy for readdir() is to use the position pointer as 1154 * an index into the array of all dentries. On entry, it points 1155 * to the first unread dentry. If we skip any dentries, we bump 1156 * the position pointer accordingly. 1157 */ 1158 bnum = (pos * sizeof(fat_dentry_t)) / BPS(bs); 1159 while (bnum < nodep->size / BPS(bs)) { 1160 aoff64_t o; 1161 1162 rc = fat_block_get(&b, bs, nodep, bnum, 1163 BLOCK_FLAGS_NONE); 1164 if (rc != EOK) 1165 goto err; 1166 for (o = pos % (BPS(bs) / sizeof(fat_dentry_t)); 1167 o < BPS(bs) / sizeof(fat_dentry_t); 1168 o++, pos++) { 1169 d = ((fat_dentry_t *)b->data) + o; 1170 switch (fat_classify_dentry(d)) { 1171 case FAT_DENTRY_SKIP: 1172 case FAT_DENTRY_FREE: 1173 continue; 1174 case FAT_DENTRY_LAST: 1175 rc = block_put(b); 1176 if (rc != EOK) 1177 goto err; 1178 goto miss; 1179 default: 1180 case FAT_DENTRY_VALID: 1181 fat_dentry_name_get(d, name); 1182 rc = block_put(b); 1183 if (rc != EOK) 1184 goto err; 1185 goto hit; 1186 } 1187 } 1188 rc = block_put(b); 1189 if (rc != EOK) 1190 goto err; 1191 bnum++; 1192 } 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; 1110 1111 err: 1112 (void) fat_node_put(fn); 1113 async_answer_0(callid, rc); 1114 return rc; 1115 1193 1116 miss: 1117 rc = fat_directory_close(&di); 1118 if (rc != EOK) 1119 goto err; 1194 1120 rc = fat_node_put(fn); 1195 1121 async_answer_0(callid, rc != EOK ? rc : ENOENT); … … 1197 1123 return rc != EOK ? rc : ENOENT; 1198 1124 1199 err:1200 (void) fat_node_put(fn);1201 async_answer_0(callid, rc);1202 return rc;1203 1204 1125 hit: 1205 (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); 1206 1132 bytes = (pos - spos) + 1; 1207 1133 } … … 1231 1157 return ENOENT; 1232 1158 nodep = FAT_NODE(fn); 1233 1159 1234 1160 ipc_callid_t callid; 1235 1161 size_t len; … … 1247 1173 * but this one greatly simplifies fat_write(). Note that we can afford 1248 1174 * to do this because the client must be ready to handle the return 1249 * value signalizing a smaller number of bytes written. 1250 */ 1175 * value signalizing a smaller number of bytes written. 1176 */ 1251 1177 bytes = min(len, BPS(bs) - pos % BPS(bs)); 1252 1178 if (bytes == BPS(bs)) 1253 1179 flags |= BLOCK_FLAGS_NOREAD; 1254 1180 1255 1181 boundary = ROUND_UP(nodep->size, BPC(bs)); 1256 1182 if (pos < boundary) { … … 1295 1221 */ 1296 1222 unsigned nclsts; 1297 fat_cluster_t mcl, lcl; 1298 1223 fat_cluster_t mcl, lcl; 1224 1299 1225 nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs); 1300 1226 /* create an independent chain of nclsts clusters in all FATs */ … … 1380 1306 nodep->size = size; 1381 1307 nodep->dirty = true; /* need to sync node */ 1382 rc = EOK; 1308 rc = EOK; 1383 1309 } else { 1384 1310 /* … … 1401 1327 nodep->size = size; 1402 1328 nodep->dirty = true; /* need to sync node */ 1403 rc = EOK; 1329 rc = EOK; 1404 1330 } 1405 1331 out: … … 1444 1370 if (!fn) 1445 1371 return ENOENT; 1446 1372 1447 1373 fat_node_t *nodep = FAT_NODE(fn); 1448 1374 1449 1375 nodep->dirty = true; 1450 1376 rc = fat_node_sync(nodep); 1451 1377 1452 1378 fat_node_put(fn); 1453 1379 return rc; -
uspace/srv/fs/locfs/locfs_ops.c
rbb74dabe rc05642d 418 418 } 419 419 420 static service_id_t locfs_ device_get(fs_node_t *fn)420 static service_id_t locfs_service_get(fs_node_t *fn) 421 421 { 422 422 locfs_node_t *node = (locfs_node_t *) fn->data; … … 445 445 .is_directory = locfs_is_directory, 446 446 .is_file = locfs_is_file, 447 . device_get = locfs_device_get447 .service_get = locfs_service_get 448 448 }; 449 449 -
uspace/srv/fs/tmpfs/tmpfs_ops.c
rbb74dabe rc05642d 114 114 } 115 115 116 static service_id_t tmpfs_ device_get(fs_node_t *fn)116 static service_id_t tmpfs_service_get(fs_node_t *fn) 117 117 { 118 118 return 0; … … 136 136 .is_directory = tmpfs_is_directory, 137 137 .is_file = tmpfs_is_file, 138 . device_get = tmpfs_device_get138 .service_get = tmpfs_service_get 139 139 }; 140 140 -
uspace/srv/loc/loc.c
rbb74dabe rc05642d 1231 1231 svc = loc_service_find_id(svc_id); 1232 1232 1233 if (cat == NULL || svc == NULL) { 1234 fibril_mutex_unlock(&cdir.mutex); 1235 fibril_mutex_unlock(&services_list_mutex); 1236 async_answer_0(iid, ENOENT); 1237 return; 1238 } 1239 1233 1240 fibril_mutex_lock(&cat->mutex); 1234 1241 retval = category_add_service(cat, svc); … … 1270 1277 categ_dir_add_cat(&cdir, cat); 1271 1278 1279 cat = category_new("test3"); 1280 categ_dir_add_cat(&cdir, cat); 1281 1272 1282 cat = category_new("usbhc"); 1273 1283 categ_dir_add_cat(&cdir, cat); 1274 1284 1285 cat = category_new("virt-null"); 1286 categ_dir_add_cat(&cdir, cat); 1287 1275 1288 cat = category_new("virtual"); 1276 1289 categ_dir_add_cat(&cdir, cat); 1290 1277 1291 1278 1292 return true;
Note:
See TracChangeset
for help on using the changeset viewer.
