Changeset f3504c1 in mainline for uspace/srv/fs/exfat/exfat_ops.c
- Timestamp:
- 2017-07-11T19:05:33Z (8 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 94c05b89
- Parents:
- b2906c0
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/exfat/exfat_ops.c
rb2906c0 rf3504c1 1013 1013 }; 1014 1014 1015 static int exfat_fs_open(service_id_t service_id, enum cache_mode cmode, 1016 fs_node_t **rrfn, exfat_idx_t **rridxp, vfs_fs_probe_info_t *info) 1017 { 1018 int rc; 1019 exfat_node_t *rootp = NULL, *bitmapp = NULL, *uctablep = NULL; 1020 exfat_bs_t *bs; 1021 1022 /* initialize libblock */ 1023 rc = block_init(service_id, BS_SIZE); 1024 if (rc != EOK) 1025 return rc; 1026 1027 /* prepare the boot block */ 1028 rc = block_bb_read(service_id, BS_BLOCK); 1029 if (rc != EOK) { 1030 block_fini(service_id); 1031 return rc; 1032 } 1033 1034 /* get the buffer with the boot sector */ 1035 bs = block_bb_get(service_id); 1036 1037 /* Do some simple sanity checks on the file system. */ 1038 rc = exfat_sanity_check(bs); 1039 if (rc != EOK) { 1040 (void) block_cache_fini(service_id); 1041 block_fini(service_id); 1042 return rc; 1043 } 1044 1045 /* Initialize the block cache */ 1046 rc = block_cache_init(service_id, BPS(bs), 0 /* XXX */, cmode); 1047 if (rc != EOK) { 1048 block_fini(service_id); 1049 return rc; 1050 } 1051 1052 rc = exfat_idx_init_by_service_id(service_id); 1053 if (rc != EOK) { 1054 (void) block_cache_fini(service_id); 1055 block_fini(service_id); 1056 return rc; 1057 } 1058 1059 /* Initialize the root node. */ 1060 rc = exfat_node_get_new_by_pos(&rootp, service_id, EXFAT_ROOT_PAR, 1061 EXFAT_ROOT_POS); 1062 if (rc!=EOK) { 1063 (void) block_cache_fini(service_id); 1064 block_fini(service_id); 1065 exfat_idx_fini_by_service_id(service_id); 1066 return ENOMEM; 1067 } 1068 assert(rootp->idx->index == EXFAT_ROOT_IDX); 1069 1070 rootp->type = EXFAT_DIRECTORY; 1071 rootp->firstc = ROOT_FC(bs); 1072 rootp->fragmented = true; 1073 rootp->refcnt = 1; 1074 rootp->lnkcnt = 0; /* FS root is not linked */ 1075 1076 uint32_t clusters; 1077 rc = exfat_clusters_get(&clusters, bs, service_id, rootp->firstc); 1078 if (rc != EOK) { 1079 free(rootp); 1080 (void) block_cache_fini(service_id); 1081 block_fini(service_id); 1082 exfat_idx_fini_by_service_id(service_id); 1083 return ENOTSUP; 1084 } 1085 rootp->size = BPS(bs) * SPC(bs) * clusters; 1086 fibril_mutex_unlock(&rootp->idx->lock); 1087 1088 /* Open root directory and looking for Bitmap and UC-Table */ 1089 exfat_directory_t di; 1090 exfat_dentry_t *de; 1091 rc = exfat_directory_open(rootp, &di); 1092 if (rc != EOK) { 1093 free(rootp); 1094 (void) block_cache_fini(service_id); 1095 block_fini(service_id); 1096 exfat_idx_fini_by_service_id(service_id); 1097 return ENOTSUP; 1098 } 1099 1100 /* Initialize the bitmap node. */ 1101 rc = exfat_directory_find(&di, EXFAT_DENTRY_BITMAP, &de); 1102 if (rc != EOK) { 1103 free(rootp); 1104 (void) block_cache_fini(service_id); 1105 block_fini(service_id); 1106 exfat_idx_fini_by_service_id(service_id); 1107 return ENOTSUP; 1108 } 1109 1110 rc = exfat_node_get_new_by_pos(&bitmapp, service_id, rootp->firstc, 1111 di.pos); 1112 if (rc != EOK) { 1113 free(rootp); 1114 (void) block_cache_fini(service_id); 1115 block_fini(service_id); 1116 exfat_idx_fini_by_service_id(service_id); 1117 return ENOMEM; 1118 } 1119 assert(bitmapp->idx->index == EXFAT_BITMAP_IDX); 1120 fibril_mutex_unlock(&bitmapp->idx->lock); 1121 1122 bitmapp->type = EXFAT_BITMAP; 1123 bitmapp->firstc = uint32_t_le2host(de->bitmap.firstc); 1124 bitmapp->fragmented = true; 1125 bitmapp->idx->parent_fragmented = true; 1126 bitmapp->refcnt = 1; 1127 bitmapp->lnkcnt = 0; 1128 bitmapp->size = uint64_t_le2host(de->bitmap.size); 1129 1130 /* Initialize the uctable node. */ 1131 rc = exfat_directory_seek(&di, 0); 1132 if (rc != EOK) { 1133 free(rootp); 1134 free(bitmapp); 1135 (void) block_cache_fini(service_id); 1136 block_fini(service_id); 1137 exfat_idx_fini_by_service_id(service_id); 1138 return ENOTSUP; 1139 } 1140 1141 rc = exfat_directory_find(&di, EXFAT_DENTRY_UCTABLE, &de); 1142 if (rc != EOK) { 1143 free(rootp); 1144 free(bitmapp); 1145 (void) block_cache_fini(service_id); 1146 block_fini(service_id); 1147 exfat_idx_fini_by_service_id(service_id); 1148 return ENOTSUP; 1149 } 1150 1151 rc = exfat_node_get_new_by_pos(&uctablep, service_id, rootp->firstc, 1152 di.pos); 1153 if (rc != EOK) { 1154 free(rootp); 1155 free(bitmapp); 1156 (void) block_cache_fini(service_id); 1157 block_fini(service_id); 1158 exfat_idx_fini_by_service_id(service_id); 1159 return ENOMEM; 1160 } 1161 assert(uctablep->idx->index == EXFAT_UCTABLE_IDX); 1162 fibril_mutex_unlock(&uctablep->idx->lock); 1163 1164 uctablep->type = EXFAT_UCTABLE; 1165 uctablep->firstc = uint32_t_le2host(de->uctable.firstc); 1166 uctablep->fragmented = true; 1167 uctablep->idx->parent_fragmented = true; 1168 uctablep->refcnt = 1; 1169 uctablep->lnkcnt = 0; 1170 uctablep->size = uint64_t_le2host(de->uctable.size); 1171 1172 if (info != NULL) { 1173 /* Read volume label. */ 1174 rc = exfat_directory_read_vollabel(&di, info->label, 1175 FS_LABEL_MAXLEN + 1); 1176 if (rc != EOK) { 1177 free(rootp); 1178 free(bitmapp); 1179 free(uctablep); 1180 (void) block_cache_fini(service_id); 1181 block_fini(service_id); 1182 exfat_idx_fini_by_service_id(service_id); 1183 return ENOTSUP; 1184 } 1185 } 1186 1187 rc = exfat_directory_close(&di); 1188 if (rc != EOK) { 1189 free(rootp); 1190 free(bitmapp); 1191 free(uctablep); 1192 (void) block_cache_fini(service_id); 1193 block_fini(service_id); 1194 exfat_idx_fini_by_service_id(service_id); 1195 return ENOMEM; 1196 } 1197 1198 /* exfat_fsinfo(bs, service_id); */ 1199 1200 *rrfn = FS_NODE(rootp); 1201 *rridxp = rootp->idx; 1202 1203 if (info != NULL) { 1204 // str_cpy(info->label, FS_LABEL_MAXLEN + 1, label); 1205 } 1206 1207 return EOK; 1208 } 1209 1210 static void exfat_fs_close(service_id_t service_id, fs_node_t *rfn) 1211 { 1212 /* 1213 * Put the root node and force it to the FAT free node list. 1214 */ 1215 (void) exfat_node_put(rfn); 1216 (void) exfat_node_put(rfn); 1217 1218 /* 1219 * Perform cleanup of the node structures, index structures and 1220 * associated data. Write back this file system's dirty blocks and 1221 * stop using libblock for this instance. 1222 */ 1223 (void) exfat_node_fini_by_service_id(service_id); 1224 exfat_idx_fini_by_service_id(service_id); 1225 (void) block_cache_fini(service_id); 1226 block_fini(service_id); 1227 } 1228 1015 1229 1016 1230 /* … … 1054 1268 { 1055 1269 int rc; 1056 exfat_bs_t *bs; 1057 1058 /* initialize libblock */ 1059 rc = block_init(service_id, BS_SIZE); 1060 if (rc != EOK) 1061 return rc; 1062 1063 /* prepare the boot block */ 1064 rc = block_bb_read(service_id, BS_BLOCK); 1065 if (rc != EOK) { 1066 block_fini(service_id); 1067 return rc; 1068 } 1069 1070 /* get the buffer with the boot sector */ 1071 bs = block_bb_get(service_id); 1072 1073 /* Do some simple sanity checks on the file system. */ 1074 rc = exfat_sanity_check(bs); 1075 1076 (void) block_cache_fini(service_id); 1077 block_fini(service_id); 1078 return rc; 1270 exfat_idx_t *ridxp; 1271 fs_node_t *rfn; 1272 1273 rc = exfat_fs_open(service_id, CACHE_MODE_WT, &rfn, &ridxp, info); 1274 if (rc != EOK) 1275 return rc; 1276 1277 exfat_fs_close(service_id, rfn); 1278 return EOK; 1079 1279 } 1080 1280 … … 1084 1284 { 1085 1285 int rc; 1086 exfat_node_t *rootp = NULL, *bitmapp = NULL, *uctablep = NULL;1087 1286 enum cache_mode cmode; 1088 exfat_bs_t *bs; 1287 exfat_idx_t *ridxp; 1288 fs_node_t *rfn; 1089 1289 1090 1290 /* Check for option enabling write through. */ … … 1094 1294 cmode = CACHE_MODE_WB; 1095 1295 1096 /* initialize libblock */ 1097 rc = block_init(service_id, BS_SIZE); 1098 if (rc != EOK) 1099 return rc; 1100 1101 /* prepare the boot block */ 1102 rc = block_bb_read(service_id, BS_BLOCK); 1103 if (rc != EOK) { 1104 block_fini(service_id); 1105 return rc; 1106 } 1107 1108 /* get the buffer with the boot sector */ 1109 bs = block_bb_get(service_id); 1110 1111 /* Do some simple sanity checks on the file system. */ 1112 rc = exfat_sanity_check(bs); 1113 if (rc != EOK) { 1114 (void) block_cache_fini(service_id); 1115 block_fini(service_id); 1116 return rc; 1117 } 1118 1119 /* Initialize the block cache */ 1120 rc = block_cache_init(service_id, BPS(bs), 0 /* XXX */, cmode); 1121 if (rc != EOK) { 1122 block_fini(service_id); 1123 return rc; 1124 } 1125 1126 rc = exfat_idx_init_by_service_id(service_id); 1127 if (rc != EOK) { 1128 (void) block_cache_fini(service_id); 1129 block_fini(service_id); 1130 return rc; 1131 } 1132 1133 /* Initialize the root node. */ 1134 rc = exfat_node_get_new_by_pos(&rootp, service_id, EXFAT_ROOT_PAR, 1135 EXFAT_ROOT_POS); 1136 if (rc!=EOK) { 1137 (void) block_cache_fini(service_id); 1138 block_fini(service_id); 1139 exfat_idx_fini_by_service_id(service_id); 1140 return ENOMEM; 1141 } 1142 assert(rootp->idx->index == EXFAT_ROOT_IDX); 1143 1144 rootp->type = EXFAT_DIRECTORY; 1145 rootp->firstc = ROOT_FC(bs); 1146 rootp->fragmented = true; 1147 rootp->refcnt = 1; 1148 rootp->lnkcnt = 0; /* FS root is not linked */ 1149 1150 uint32_t clusters; 1151 rc = exfat_clusters_get(&clusters, bs, service_id, rootp->firstc); 1152 if (rc != EOK) { 1153 free(rootp); 1154 (void) block_cache_fini(service_id); 1155 block_fini(service_id); 1156 exfat_idx_fini_by_service_id(service_id); 1157 return ENOTSUP; 1158 } 1159 rootp->size = BPS(bs) * SPC(bs) * clusters; 1160 fibril_mutex_unlock(&rootp->idx->lock); 1161 1162 /* Open root directory and looking for Bitmap and UC-Table */ 1163 exfat_directory_t di; 1164 exfat_dentry_t *de; 1165 rc = exfat_directory_open(rootp, &di); 1166 if (rc != EOK) { 1167 free(rootp); 1168 (void) block_cache_fini(service_id); 1169 block_fini(service_id); 1170 exfat_idx_fini_by_service_id(service_id); 1171 return ENOTSUP; 1172 } 1173 1174 /* Initialize the bitmap node. */ 1175 rc = exfat_directory_find(&di, EXFAT_DENTRY_BITMAP, &de); 1176 if (rc != EOK) { 1177 free(rootp); 1178 (void) block_cache_fini(service_id); 1179 block_fini(service_id); 1180 exfat_idx_fini_by_service_id(service_id); 1181 return ENOTSUP; 1182 } 1183 1184 rc = exfat_node_get_new_by_pos(&bitmapp, service_id, rootp->firstc, 1185 di.pos); 1186 if (rc != EOK) { 1187 free(rootp); 1188 (void) block_cache_fini(service_id); 1189 block_fini(service_id); 1190 exfat_idx_fini_by_service_id(service_id); 1191 return ENOMEM; 1192 } 1193 assert(bitmapp->idx->index == EXFAT_BITMAP_IDX); 1194 fibril_mutex_unlock(&bitmapp->idx->lock); 1195 1196 bitmapp->type = EXFAT_BITMAP; 1197 bitmapp->firstc = uint32_t_le2host(de->bitmap.firstc); 1198 bitmapp->fragmented = true; 1199 bitmapp->idx->parent_fragmented = true; 1200 bitmapp->refcnt = 1; 1201 bitmapp->lnkcnt = 0; 1202 bitmapp->size = uint64_t_le2host(de->bitmap.size); 1203 1204 /* Initialize the uctable node. */ 1205 rc = exfat_directory_seek(&di, 0); 1206 if (rc != EOK) { 1207 free(rootp); 1208 free(bitmapp); 1209 (void) block_cache_fini(service_id); 1210 block_fini(service_id); 1211 exfat_idx_fini_by_service_id(service_id); 1212 return ENOTSUP; 1213 } 1214 1215 rc = exfat_directory_find(&di, EXFAT_DENTRY_UCTABLE, &de); 1216 if (rc != EOK) { 1217 free(rootp); 1218 free(bitmapp); 1219 (void) block_cache_fini(service_id); 1220 block_fini(service_id); 1221 exfat_idx_fini_by_service_id(service_id); 1222 return ENOTSUP; 1223 } 1224 1225 rc = exfat_node_get_new_by_pos(&uctablep, service_id, rootp->firstc, 1226 di.pos); 1227 if (rc != EOK) { 1228 free(rootp); 1229 free(bitmapp); 1230 (void) block_cache_fini(service_id); 1231 block_fini(service_id); 1232 exfat_idx_fini_by_service_id(service_id); 1233 return ENOMEM; 1234 } 1235 assert(uctablep->idx->index == EXFAT_UCTABLE_IDX); 1236 fibril_mutex_unlock(&uctablep->idx->lock); 1237 1238 uctablep->type = EXFAT_UCTABLE; 1239 uctablep->firstc = uint32_t_le2host(de->uctable.firstc); 1240 uctablep->fragmented = true; 1241 uctablep->idx->parent_fragmented = true; 1242 uctablep->refcnt = 1; 1243 uctablep->lnkcnt = 0; 1244 uctablep->size = uint64_t_le2host(de->uctable.size); 1245 1246 rc = exfat_directory_close(&di); 1247 if (rc != EOK) { 1248 free(rootp); 1249 free(bitmapp); 1250 free(uctablep); 1251 (void) block_cache_fini(service_id); 1252 block_fini(service_id); 1253 exfat_idx_fini_by_service_id(service_id); 1254 return ENOMEM; 1255 } 1256 1257 /* exfat_fsinfo(bs, service_id); */ 1258 1259 *index = rootp->idx->index; 1260 *size = rootp->size; 1261 1296 rc = exfat_fs_open(service_id, cmode, &rfn, &ridxp, NULL); 1297 if (rc != EOK) 1298 return rc; 1299 1300 *index = ridxp->index; 1301 *size = EXFAT_NODE(rfn)->size; 1302 1262 1303 return EOK; 1263 1304 } … … 1265 1306 static int exfat_unmounted(service_id_t service_id) 1266 1307 { 1267 fs_node_t *fn; 1268 exfat_node_t *nodep; 1269 int rc; 1270 1271 rc = exfat_root_get(&fn, service_id); 1272 if (rc != EOK) 1273 return rc; 1274 nodep = EXFAT_NODE(fn); 1275 1276 /* 1277 * We expect exactly two references on the root node. One for the 1278 * fat_root_get() above and one created in fat_mounted(). 1279 */ 1280 if (nodep->refcnt != 2) { 1281 (void) exfat_node_put(fn); 1282 return EBUSY; 1283 } 1284 1285 /* 1286 * Put the root node and force it to the FAT free node list. 1287 */ 1288 (void) exfat_node_put(fn); 1289 (void) exfat_node_put(fn); 1290 1291 /* 1292 * Perform cleanup of the node structures, index structures and 1293 * associated data. Write back this file system's dirty blocks and 1294 * stop using libblock for this instance. 1295 */ 1296 (void) exfat_node_fini_by_service_id(service_id); 1297 exfat_idx_fini_by_service_id(service_id); 1298 (void) block_cache_fini(service_id); 1299 block_fini(service_id); 1300 1308 fs_node_t *rfn; 1309 int rc; 1310 1311 rc = exfat_root_get(&rfn, service_id); 1312 if (rc != EOK) 1313 return rc; 1314 1315 exfat_fs_close(service_id, rfn); 1301 1316 return EOK; 1302 1317 } … … 1363 1378 return ENOTSUP; 1364 1379 } 1365 1380 1366 1381 aoff64_t spos = pos; 1367 1382 char name[EXFAT_FILENAME_LEN + 1];
Note:
See TracChangeset
for help on using the changeset viewer.