Changeset 19f24fd in mainline for uspace/srv/fs/fat/fat_ops.c
- Timestamp:
- 2010-02-05T22:25:52Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- dafa2d04
- Parents:
- 83349b03 (diff), d42976c (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_ops.c
r83349b03 r19f24fd 139 139 } 140 140 141 static int fat_node_fini_by_dev_handle(dev_handle_t dev_handle) 142 { 143 link_t *lnk; 144 fat_node_t *nodep; 145 int rc; 146 147 /* 148 * We are called from fat_unmounted() and assume that there are already 149 * no nodes belonging to this instance with non-zero refcount. Therefore 150 * it is sufficient to clean up only the FAT free node list. 151 */ 152 153 restart: 154 fibril_mutex_lock(&ffn_mutex); 155 for (lnk = ffn_head.next; lnk != &ffn_head; lnk = lnk->next) { 156 nodep = list_get_instance(lnk, fat_node_t, ffn_link); 157 if (!fibril_mutex_trylock(&nodep->lock)) { 158 fibril_mutex_unlock(&ffn_mutex); 159 goto restart; 160 } 161 if (!fibril_mutex_trylock(&nodep->idx->lock)) { 162 fibril_mutex_unlock(&nodep->lock); 163 fibril_mutex_unlock(&ffn_mutex); 164 goto restart; 165 } 166 if (nodep->idx->dev_handle != dev_handle) { 167 fibril_mutex_unlock(&nodep->idx->lock); 168 fibril_mutex_unlock(&nodep->lock); 169 continue; 170 } 171 172 list_remove(&nodep->ffn_link); 173 fibril_mutex_unlock(&ffn_mutex); 174 175 /* 176 * We can unlock the node and its index structure because we are 177 * the last player on this playground and VFS is preventing new 178 * players from entering. 179 */ 180 fibril_mutex_unlock(&nodep->idx->lock); 181 fibril_mutex_unlock(&nodep->lock); 182 183 if (nodep->dirty) { 184 rc = fat_node_sync(nodep); 185 if (rc != EOK) 186 return rc; 187 } 188 nodep->idx->nodep = NULL; 189 free(nodep->bp); 190 free(nodep); 191 192 /* Need to restart because we changed the ffn_head list. */ 193 goto restart; 194 } 195 fibril_mutex_unlock(&ffn_mutex); 196 197 return EOK; 198 } 199 141 200 static int fat_node_get_new(fat_node_t **nodepp) 142 201 { … … 290 349 291 350 *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 media298 * descriptor. This is used to rule out cases when a device obviously299 * 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 root331 * directory and non-root directories uniformly in some places.332 * It can be removed provided that functions such as fat_read() are333 * 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 are356 * set to one.357 */358 if ((e0 >> 8) != 0xff || e1 != 0xffff)359 return ENOTSUP;360 }361 362 351 return EOK; 363 352 } … … 985 974 uint16_t bps; 986 975 uint16_t rde; 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'; 976 977 /* Accept the mount options */ 978 char *opts; 979 int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL); 980 981 if (rc != EOK) { 982 ipc_answer_0(rid, rc); 983 return; 984 } 1010 985 1011 986 /* Check for option enabling write through. */ … … 1015 990 cmode = CACHE_MODE_WB; 1016 991 992 free(opts); 993 1017 994 /* initialize libblock */ 1018 995 rc = block_init(dev_handle, BS_SIZE); … … 1054 1031 rc = fat_sanity_check(bs, dev_handle); 1055 1032 if (rc != EOK) { 1033 (void) block_cache_fini(dev_handle); 1056 1034 block_fini(dev_handle); 1057 1035 ipc_answer_0(rid, rc); … … 1061 1039 rc = fat_idx_init_by_dev_handle(dev_handle); 1062 1040 if (rc != EOK) { 1041 (void) block_cache_fini(dev_handle); 1063 1042 block_fini(dev_handle); 1064 1043 ipc_answer_0(rid, rc); … … 1069 1048 fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t)); 1070 1049 if (!rfn) { 1050 (void) block_cache_fini(dev_handle); 1071 1051 block_fini(dev_handle); 1072 1052 fat_idx_fini_by_dev_handle(dev_handle); … … 1078 1058 if (!rootp) { 1079 1059 free(rfn); 1060 (void) block_cache_fini(dev_handle); 1080 1061 block_fini(dev_handle); 1081 1062 fat_idx_fini_by_dev_handle(dev_handle); … … 1089 1070 free(rfn); 1090 1071 free(rootp); 1072 (void) block_cache_fini(dev_handle); 1091 1073 block_fini(dev_handle); 1092 1074 fat_idx_fini_by_dev_handle(dev_handle); … … 1115 1097 { 1116 1098 libfs_mount(&fat_libfs_ops, fat_reg.fs_handle, rid, request); 1099 } 1100 1101 void fat_unmounted(ipc_callid_t rid, ipc_call_t *request) 1102 { 1103 dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); 1104 fs_node_t *fn; 1105 fat_node_t *nodep; 1106 int rc; 1107 1108 rc = fat_root_get(&fn, dev_handle); 1109 if (rc != EOK) { 1110 ipc_answer_0(rid, rc); 1111 return; 1112 } 1113 nodep = FAT_NODE(fn); 1114 1115 /* 1116 * We expect exactly two references on the root node. One for the 1117 * fat_root_get() above and one created in fat_mounted(). 1118 */ 1119 if (nodep->refcnt != 2) { 1120 (void) fat_node_put(fn); 1121 ipc_answer_0(rid, EBUSY); 1122 return; 1123 } 1124 1125 /* 1126 * Put the root node and force it to the FAT free node list. 1127 */ 1128 (void) fat_node_put(fn); 1129 (void) fat_node_put(fn); 1130 1131 /* 1132 * Perform cleanup of the node structures, index structures and 1133 * associated data. Write back this file system's dirty blocks and 1134 * stop using libblock for this instance. 1135 */ 1136 (void) fat_node_fini_by_dev_handle(dev_handle); 1137 fat_idx_fini_by_dev_handle(dev_handle); 1138 (void) block_cache_fini(dev_handle); 1139 block_fini(dev_handle); 1140 1141 ipc_answer_0(rid, EOK); 1142 } 1143 1144 void fat_unmount(ipc_callid_t rid, ipc_call_t *request) 1145 { 1146 libfs_unmount(&fat_libfs_ops, rid, request); 1117 1147 } 1118 1148
Note:
See TracChangeset
for help on using the changeset viewer.