Changes in uspace/srv/fs/fat/fat_ops.c [ed903174:92bee46] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_ops.c
red903174 r92bee46 45 45 #include <ipc/services.h> 46 46 #include <ipc/devmap.h> 47 #include <macros.h>48 47 #include <async.h> 49 48 #include <errno.h> … … 80 79 static int fat_has_children(bool *, fs_node_t *); 81 80 static fs_index_t fat_index_get(fs_node_t *); 82 static aoff64_t fat_size_get(fs_node_t *);81 static size_t fat_size_get(fs_node_t *); 83 82 static unsigned fat_lnkcnt_get(fs_node_t *); 84 83 static char fat_plb_get_char(unsigned); … … 138 137 rc = block_put(b); 139 138 return rc; 140 }141 142 static int fat_node_fini_by_dev_handle(dev_handle_t dev_handle)143 {144 link_t *lnk;145 fat_node_t *nodep;146 int rc;147 148 /*149 * We are called from fat_unmounted() and assume that there are already150 * no nodes belonging to this instance with non-zero refcount. Therefore151 * it is sufficient to clean up only the FAT free node list.152 */153 154 restart:155 fibril_mutex_lock(&ffn_mutex);156 for (lnk = ffn_head.next; lnk != &ffn_head; lnk = lnk->next) {157 nodep = list_get_instance(lnk, fat_node_t, ffn_link);158 if (!fibril_mutex_trylock(&nodep->lock)) {159 fibril_mutex_unlock(&ffn_mutex);160 goto restart;161 }162 if (!fibril_mutex_trylock(&nodep->idx->lock)) {163 fibril_mutex_unlock(&nodep->lock);164 fibril_mutex_unlock(&ffn_mutex);165 goto restart;166 }167 if (nodep->idx->dev_handle != dev_handle) {168 fibril_mutex_unlock(&nodep->idx->lock);169 fibril_mutex_unlock(&nodep->lock);170 continue;171 }172 173 list_remove(&nodep->ffn_link);174 fibril_mutex_unlock(&ffn_mutex);175 176 /*177 * We can unlock the node and its index structure because we are178 * the last player on this playground and VFS is preventing new179 * players from entering.180 */181 fibril_mutex_unlock(&nodep->idx->lock);182 fibril_mutex_unlock(&nodep->lock);183 184 if (nodep->dirty) {185 rc = fat_node_sync(nodep);186 if (rc != EOK)187 return rc;188 }189 nodep->idx->nodep = NULL;190 free(nodep->bp);191 free(nodep);192 193 /* Need to restart because we changed the ffn_head list. */194 goto restart;195 }196 fibril_mutex_unlock(&ffn_mutex);197 198 return EOK;199 139 } 200 140 … … 350 290 351 291 *nodepp = nodep; 292 return EOK; 293 } 294 295 /** Perform basic sanity checks on the file system. 296 * 297 * Verify if values of boot sector fields are sane. Also verify media 298 * descriptor. This is used to rule out cases when a device obviously 299 * does not contain a fat file system. 300 */ 301 static int fat_sanity_check(fat_bs_t *bs, dev_handle_t dev_handle) 302 { 303 fat_cluster_t e0, e1; 304 unsigned fat_no; 305 int rc; 306 307 /* Check number of FATs. */ 308 if (bs->fatcnt == 0) 309 return ENOTSUP; 310 311 /* Check total number of sectors. */ 312 313 if (bs->totsec16 == 0 && bs->totsec32 == 0) 314 return ENOTSUP; 315 316 if (bs->totsec16 != 0 && bs->totsec32 != 0 && 317 bs->totsec16 != bs->totsec32) 318 return ENOTSUP; 319 320 /* Check media descriptor. Must be between 0xf0 and 0xff. */ 321 if ((bs->mdesc & 0xf0) != 0xf0) 322 return ENOTSUP; 323 324 /* Check number of sectors per FAT. */ 325 if (bs->sec_per_fat == 0) 326 return ENOTSUP; 327 328 /* 329 * Check that the root directory entries take up whole blocks. 330 * This check is rather strict, but it allows us to treat the root 331 * directory and non-root directories uniformly in some places. 332 * It can be removed provided that functions such as fat_read() are 333 * sanitized to support file systems with this property. 334 */ 335 if ((uint16_t_le2host(bs->root_ent_max) * sizeof(fat_dentry_t)) % 336 uint16_t_le2host(bs->bps) != 0) 337 return ENOTSUP; 338 339 /* Check signature of each FAT. */ 340 341 for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) { 342 rc = fat_get_cluster(bs, dev_handle, fat_no, 0, &e0); 343 if (rc != EOK) 344 return EIO; 345 346 rc = fat_get_cluster(bs, dev_handle, fat_no, 1, &e1); 347 if (rc != EOK) 348 return EIO; 349 350 /* Check that first byte of FAT contains the media descriptor. */ 351 if ((e0 & 0xff) != bs->mdesc) 352 return ENOTSUP; 353 354 /* 355 * Check that remaining bits of the first two entries are 356 * set to one. 357 */ 358 if ((e0 >> 8) != 0xff || e1 != 0xffff) 359 return ENOTSUP; 360 } 361 352 362 return EOK; 353 363 } … … 723 733 fibril_mutex_lock(&childp->idx->lock); 724 734 725 if (childp->type == FAT_DIRECTORY) { 735 /* 736 * If possible, create the Sub-directory Identifier Entry and the 737 * Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries 738 * are not mandatory according to Standard ECMA-107 and HelenOS VFS does 739 * not use them anyway, so this is rather a sign of our good will. 740 */ 741 rc = fat_block_get(&b, bs, childp, 0, BLOCK_FLAGS_NONE); 742 if (rc != EOK) { 726 743 /* 727 * If possible, create the Sub-directory Identifier Entry and 728 * the Sub-directory Parent Pointer Entry (i.e. "." and ".."). 729 * These entries are not mandatory according to Standard 730 * ECMA-107 and HelenOS VFS does not use them anyway, so this is 731 * rather a sign of our good will. 744 * Rather than returning an error, simply skip the creation of 745 * these two entries. 732 746 */ 733 rc = fat_block_get(&b, bs, childp, 0, BLOCK_FLAGS_NONE); 734 if (rc != EOK) { 735 /* 736 * Rather than returning an error, simply skip the 737 * creation of these two entries. 738 */ 739 goto skip_dots; 740 } 741 d = (fat_dentry_t *) b->data; 742 if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) || 743 (str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) { 744 memset(d, 0, sizeof(fat_dentry_t)); 745 str_cpy((char *) d->name, 8, FAT_NAME_DOT); 746 str_cpy((char *) d->ext, 3, FAT_EXT_PAD); 747 d->attr = FAT_ATTR_SUBDIR; 748 d->firstc = host2uint16_t_le(childp->firstc); 749 /* TODO: initialize also the date/time members. */ 750 } 751 d++; 752 if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) || 753 (str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) { 754 memset(d, 0, sizeof(fat_dentry_t)); 755 str_cpy((char *) d->name, 8, FAT_NAME_DOT_DOT); 756 str_cpy((char *) d->ext, 3, FAT_EXT_PAD); 757 d->attr = FAT_ATTR_SUBDIR; 758 d->firstc = (parentp->firstc == FAT_CLST_ROOT) ? 759 host2uint16_t_le(FAT_CLST_RES0) : 760 host2uint16_t_le(parentp->firstc); 761 /* TODO: initialize also the date/time members. */ 762 } 763 b->dirty = true; /* need to sync block */ 764 /* 765 * Ignore the return value as we would have fallen through on error 766 * anyway. 767 */ 768 (void) block_put(b); 769 } 747 goto skip_dots; 748 } 749 d = (fat_dentry_t *)b->data; 750 if (fat_classify_dentry(d) == FAT_DENTRY_LAST || 751 str_cmp(d->name, FAT_NAME_DOT) == 0) { 752 memset(d, 0, sizeof(fat_dentry_t)); 753 str_cpy(d->name, 8, FAT_NAME_DOT); 754 str_cpy(d->ext, 3, FAT_EXT_PAD); 755 d->attr = FAT_ATTR_SUBDIR; 756 d->firstc = host2uint16_t_le(childp->firstc); 757 /* TODO: initialize also the date/time members. */ 758 } 759 d++; 760 if (fat_classify_dentry(d) == FAT_DENTRY_LAST || 761 str_cmp(d->name, FAT_NAME_DOT_DOT) == 0) { 762 memset(d, 0, sizeof(fat_dentry_t)); 763 str_cpy(d->name, 8, FAT_NAME_DOT_DOT); 764 str_cpy(d->ext, 3, FAT_EXT_PAD); 765 d->attr = FAT_ATTR_SUBDIR; 766 d->firstc = (parentp->firstc == FAT_CLST_ROOT) ? 767 host2uint16_t_le(FAT_CLST_RES0) : 768 host2uint16_t_le(parentp->firstc); 769 /* TODO: initialize also the date/time members. */ 770 } 771 b->dirty = true; /* need to sync block */ 772 /* 773 * Ignore the return value as we would have fallen through on error 774 * anyway. 775 */ 776 (void) block_put(b); 770 777 skip_dots: 771 778 … … 916 923 } 917 924 918 aoff64_t fat_size_get(fs_node_t *fn)925 size_t fat_size_get(fs_node_t *fn) 919 926 { 920 927 return FAT_NODE(fn)->size; … … 978 985 uint16_t bps; 979 986 uint16_t rde; 980 981 /* Accept the mount options */ 982 char *opts; 983 int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL); 984 985 if (rc != EOK) { 986 ipc_answer_0(rid, rc); 987 return; 988 } 987 int rc; 988 989 /* accept the mount options */ 990 ipc_callid_t callid; 991 size_t size; 992 if (!async_data_write_receive(&callid, &size)) { 993 ipc_answer_0(callid, EINVAL); 994 ipc_answer_0(rid, EINVAL); 995 return; 996 } 997 char *opts = malloc(size + 1); 998 if (!opts) { 999 ipc_answer_0(callid, ENOMEM); 1000 ipc_answer_0(rid, ENOMEM); 1001 return; 1002 } 1003 ipcarg_t retval = async_data_write_finalize(callid, opts, size); 1004 if (retval != EOK) { 1005 ipc_answer_0(rid, retval); 1006 free(opts); 1007 return; 1008 } 1009 opts[size] = '\0'; 989 1010 990 1011 /* Check for option enabling write through. */ … … 994 1015 cmode = CACHE_MODE_WB; 995 1016 996 free(opts);997 998 1017 /* initialize libblock */ 999 1018 rc = block_init(dev_handle, BS_SIZE); … … 1035 1054 rc = fat_sanity_check(bs, dev_handle); 1036 1055 if (rc != EOK) { 1037 (void) block_cache_fini(dev_handle);1038 1056 block_fini(dev_handle); 1039 1057 ipc_answer_0(rid, rc); … … 1043 1061 rc = fat_idx_init_by_dev_handle(dev_handle); 1044 1062 if (rc != EOK) { 1045 (void) block_cache_fini(dev_handle);1046 1063 block_fini(dev_handle); 1047 1064 ipc_answer_0(rid, rc); … … 1052 1069 fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t)); 1053 1070 if (!rfn) { 1054 (void) block_cache_fini(dev_handle);1055 1071 block_fini(dev_handle); 1056 1072 fat_idx_fini_by_dev_handle(dev_handle); … … 1062 1078 if (!rootp) { 1063 1079 free(rfn); 1064 (void) block_cache_fini(dev_handle);1065 1080 block_fini(dev_handle); 1066 1081 fat_idx_fini_by_dev_handle(dev_handle); … … 1074 1089 free(rfn); 1075 1090 free(rootp); 1076 (void) block_cache_fini(dev_handle);1077 1091 block_fini(dev_handle); 1078 1092 fat_idx_fini_by_dev_handle(dev_handle); … … 1103 1117 } 1104 1118 1105 void fat_unmounted(ipc_callid_t rid, ipc_call_t *request)1106 {1107 dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);1108 fs_node_t *fn;1109 fat_node_t *nodep;1110 int rc;1111 1112 rc = fat_root_get(&fn, dev_handle);1113 if (rc != EOK) {1114 ipc_answer_0(rid, rc);1115 return;1116 }1117 nodep = FAT_NODE(fn);1118 1119 /*1120 * We expect exactly two references on the root node. One for the1121 * fat_root_get() above and one created in fat_mounted().1122 */1123 if (nodep->refcnt != 2) {1124 (void) fat_node_put(fn);1125 ipc_answer_0(rid, EBUSY);1126 return;1127 }1128 1129 /*1130 * Put the root node and force it to the FAT free node list.1131 */1132 (void) fat_node_put(fn);1133 (void) fat_node_put(fn);1134 1135 /*1136 * Perform cleanup of the node structures, index structures and1137 * associated data. Write back this file system's dirty blocks and1138 * stop using libblock for this instance.1139 */1140 (void) fat_node_fini_by_dev_handle(dev_handle);1141 fat_idx_fini_by_dev_handle(dev_handle);1142 (void) block_cache_fini(dev_handle);1143 block_fini(dev_handle);1144 1145 ipc_answer_0(rid, EOK);1146 }1147 1148 void fat_unmount(ipc_callid_t rid, ipc_call_t *request)1149 {1150 libfs_unmount(&fat_libfs_ops, rid, request);1151 }1152 1153 1119 void fat_lookup(ipc_callid_t rid, ipc_call_t *request) 1154 1120 { … … 1158 1124 void fat_read(ipc_callid_t rid, ipc_call_t *request) 1159 1125 { 1160 dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); 1161 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 1162 aoff64_t pos = 1163 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request)); 1126 dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); 1127 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1128 off_t pos = (off_t)IPC_GET_ARG3(*request); 1164 1129 fs_node_t *fn; 1165 1130 fat_node_t *nodep; … … 1225 1190 } else { 1226 1191 unsigned bnum; 1227 aoff64_t spos = pos;1192 off_t spos = pos; 1228 1193 char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; 1229 1194 fat_dentry_t *d; … … 1241 1206 bnum = (pos * sizeof(fat_dentry_t)) / bps; 1242 1207 while (bnum < nodep->size / bps) { 1243 aoff64_t o;1208 off_t o; 1244 1209 1245 1210 rc = fat_block_get(&b, bs, nodep, bnum, … … 1297 1262 void fat_write(ipc_callid_t rid, ipc_call_t *request) 1298 1263 { 1299 dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); 1300 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 1301 aoff64_t pos = 1302 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request)); 1264 dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); 1265 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1266 off_t pos = (off_t)IPC_GET_ARG3(*request); 1303 1267 fs_node_t *fn; 1304 1268 fat_node_t *nodep; … … 1309 1273 unsigned spc; 1310 1274 unsigned bpc; /* bytes per cluster */ 1311 aoff64_t boundary;1275 off_t boundary; 1312 1276 int flags = BLOCK_FLAGS_NONE; 1313 1277 int rc; … … 1455 1419 void fat_truncate(ipc_callid_t rid, ipc_call_t *request) 1456 1420 { 1457 dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); 1458 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 1459 aoff64_t size = 1460 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request)); 1421 dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); 1422 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1423 size_t size = (off_t)IPC_GET_ARG3(*request); 1461 1424 fs_node_t *fn; 1462 1425 fat_node_t *nodep;
Note:
See TracChangeset
for help on using the changeset viewer.