Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/exfat/exfat_ops.c

    r4f30222 r18902ca6  
    595595int exfat_node_put(fs_node_t *fn)
    596596{
     597        if (fn == NULL)
     598                return EOK;
     599
    597600        exfat_node_t *nodep = EXFAT_NODE(fn);
    598601        bool destroy = false;
     
    932935int exfat_free_block_count(service_id_t service_id, uint64_t *count)
    933936{
    934         fs_node_t *node;
     937        fs_node_t *node = NULL;
    935938        exfat_node_t *bmap_node;
    936939        exfat_bs_t *bs;
     
    945948
    946949        bs = block_bb_get(service_id);
    947         node = NULL;
    948950        rc = exfat_bitmap_get(&node, service_id);
    949951        if (rc != EOK)
     
    10131015};
    10141016
     1017static int exfat_fs_open(service_id_t service_id, enum cache_mode cmode,
     1018    fs_node_t **rrfn, exfat_idx_t **rridxp, vfs_fs_probe_info_t *info)
     1019{
     1020        int rc;
     1021        exfat_node_t *rootp = NULL, *bitmapp = NULL, *uctablep = NULL;
     1022        exfat_bs_t *bs;
     1023
     1024        /* initialize libblock */
     1025        rc = block_init(service_id, BS_SIZE);
     1026        if (rc != EOK)
     1027                return rc;
     1028
     1029        /* prepare the boot block */
     1030        rc = block_bb_read(service_id, BS_BLOCK);
     1031        if (rc != EOK) {
     1032                block_fini(service_id);
     1033                return rc;
     1034        }
     1035
     1036        /* get the buffer with the boot sector */
     1037        bs = block_bb_get(service_id);
     1038
     1039        /* Do some simple sanity checks on the file system. */
     1040        rc = exfat_sanity_check(bs);
     1041        if (rc != EOK) {
     1042                (void) block_cache_fini(service_id);
     1043                block_fini(service_id);
     1044                return rc;
     1045        }
     1046
     1047        /* Initialize the block cache */
     1048        rc = block_cache_init(service_id, BPS(bs), 0 /* XXX */, cmode);
     1049        if (rc != EOK) {
     1050                block_fini(service_id);
     1051                return rc;
     1052        }
     1053
     1054        rc = exfat_idx_init_by_service_id(service_id);
     1055        if (rc != EOK) {
     1056                (void) block_cache_fini(service_id);
     1057                block_fini(service_id);
     1058                return rc;
     1059        }
     1060
     1061        /* Initialize the root node. */
     1062        rc = exfat_node_get_new_by_pos(&rootp, service_id, EXFAT_ROOT_PAR,
     1063            EXFAT_ROOT_POS);
     1064        if (rc!=EOK) {
     1065                (void) block_cache_fini(service_id);
     1066                block_fini(service_id);
     1067                exfat_idx_fini_by_service_id(service_id);
     1068                return ENOMEM;
     1069        }
     1070        assert(rootp->idx->index == EXFAT_ROOT_IDX);
     1071
     1072        rootp->type = EXFAT_DIRECTORY;
     1073        rootp->firstc = ROOT_FC(bs);
     1074        rootp->fragmented = true;
     1075        rootp->refcnt = 1;
     1076        rootp->lnkcnt = 0;      /* FS root is not linked */
     1077
     1078        uint32_t clusters;
     1079        rc = exfat_clusters_get(&clusters, bs, service_id, rootp->firstc);
     1080        if (rc != EOK) {
     1081                free(rootp);
     1082                (void) block_cache_fini(service_id);
     1083                block_fini(service_id);
     1084                exfat_idx_fini_by_service_id(service_id);
     1085                return ENOTSUP;
     1086        }
     1087        rootp->size = BPS(bs) * SPC(bs) * clusters;
     1088        fibril_mutex_unlock(&rootp->idx->lock);
     1089
     1090        /* Open root directory and looking for Bitmap and UC-Table */
     1091        exfat_directory_t di;
     1092        exfat_dentry_t *de;
     1093        rc = exfat_directory_open(rootp, &di);
     1094        if (rc != EOK) {
     1095                free(rootp);
     1096                (void) block_cache_fini(service_id);
     1097                block_fini(service_id);
     1098                exfat_idx_fini_by_service_id(service_id);
     1099                return ENOTSUP;
     1100        }
     1101
     1102        /* Initialize the bitmap node. */
     1103        rc = exfat_directory_find(&di, EXFAT_DENTRY_BITMAP, &de);
     1104        if (rc != EOK) {
     1105                free(rootp);
     1106                (void) block_cache_fini(service_id);
     1107                block_fini(service_id);
     1108                exfat_idx_fini_by_service_id(service_id);
     1109                return ENOTSUP;
     1110        }
     1111
     1112        rc = exfat_node_get_new_by_pos(&bitmapp, service_id, rootp->firstc,
     1113            di.pos);
     1114        if (rc != EOK) {
     1115                free(rootp);
     1116                (void) block_cache_fini(service_id);
     1117                block_fini(service_id);
     1118                exfat_idx_fini_by_service_id(service_id);
     1119                return ENOMEM;
     1120        }
     1121        assert(bitmapp->idx->index == EXFAT_BITMAP_IDX);
     1122        fibril_mutex_unlock(&bitmapp->idx->lock);
     1123
     1124        bitmapp->type = EXFAT_BITMAP;
     1125        bitmapp->firstc = uint32_t_le2host(de->bitmap.firstc);
     1126        bitmapp->fragmented = true;
     1127        bitmapp->idx->parent_fragmented = true;
     1128        bitmapp->refcnt = 1;
     1129        bitmapp->lnkcnt = 0;
     1130        bitmapp->size = uint64_t_le2host(de->bitmap.size);
     1131
     1132        /* Initialize the uctable node. */
     1133        rc = exfat_directory_seek(&di, 0);
     1134        if (rc != EOK) {
     1135                free(rootp);
     1136                free(bitmapp);
     1137                (void) block_cache_fini(service_id);
     1138                block_fini(service_id);
     1139                exfat_idx_fini_by_service_id(service_id);
     1140                return ENOTSUP;
     1141        }
     1142
     1143        rc = exfat_directory_find(&di, EXFAT_DENTRY_UCTABLE, &de);
     1144        if (rc != EOK) {
     1145                free(rootp);
     1146                free(bitmapp);
     1147                (void) block_cache_fini(service_id);
     1148                block_fini(service_id);
     1149                exfat_idx_fini_by_service_id(service_id);
     1150                return ENOTSUP;
     1151        }
     1152
     1153        rc = exfat_node_get_new_by_pos(&uctablep, service_id, rootp->firstc,
     1154            di.pos);
     1155        if (rc != EOK) {
     1156                free(rootp);
     1157                free(bitmapp);
     1158                (void) block_cache_fini(service_id);
     1159                block_fini(service_id);
     1160                exfat_idx_fini_by_service_id(service_id);
     1161                return ENOMEM;
     1162        }
     1163        assert(uctablep->idx->index == EXFAT_UCTABLE_IDX);
     1164        fibril_mutex_unlock(&uctablep->idx->lock);
     1165
     1166        uctablep->type = EXFAT_UCTABLE;
     1167        uctablep->firstc = uint32_t_le2host(de->uctable.firstc);
     1168        uctablep->fragmented = true;
     1169        uctablep->idx->parent_fragmented = true;
     1170        uctablep->refcnt = 1;
     1171        uctablep->lnkcnt = 0;
     1172        uctablep->size = uint64_t_le2host(de->uctable.size);
     1173
     1174        if (info != NULL) {
     1175                /* Read volume label. */
     1176                rc = exfat_directory_read_vollabel(&di, info->label,
     1177                    FS_LABEL_MAXLEN + 1);
     1178                if (rc != EOK) {
     1179                        free(rootp);
     1180                        free(bitmapp);
     1181                        free(uctablep);
     1182                        (void) block_cache_fini(service_id);
     1183                        block_fini(service_id);
     1184                        exfat_idx_fini_by_service_id(service_id);
     1185                    return ENOTSUP;
     1186                }
     1187        }
     1188
     1189        rc = exfat_directory_close(&di);
     1190        if (rc != EOK) {
     1191                free(rootp);
     1192                free(bitmapp);
     1193                free(uctablep);
     1194                (void) block_cache_fini(service_id);
     1195                block_fini(service_id);
     1196                exfat_idx_fini_by_service_id(service_id);
     1197                return ENOMEM;
     1198        }
     1199
     1200        /* exfat_fsinfo(bs, service_id); */
     1201
     1202        *rrfn = FS_NODE(rootp);
     1203        *rridxp = rootp->idx;
     1204
     1205        if (info != NULL) {
     1206//              str_cpy(info->label, FS_LABEL_MAXLEN + 1, label);
     1207        }
     1208
     1209        return EOK;
     1210}
     1211
     1212static void exfat_fs_close(service_id_t service_id, fs_node_t *rfn)
     1213{
     1214        /*
     1215         * Put the root node and force it to the FAT free node list.
     1216         */
     1217        (void) exfat_node_put(rfn);
     1218        (void) exfat_node_put(rfn);
     1219
     1220        /*
     1221         * Perform cleanup of the node structures, index structures and
     1222         * associated data. Write back this file system's dirty blocks and
     1223         * stop using libblock for this instance.
     1224         */
     1225        (void) exfat_node_fini_by_service_id(service_id);
     1226        exfat_idx_fini_by_service_id(service_id);
     1227        (void) block_cache_fini(service_id);
     1228        block_fini(service_id);
     1229}
     1230
    10151231
    10161232/*
     
    10541270{
    10551271        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;
     1272        exfat_idx_t *ridxp;
     1273        fs_node_t *rfn;
     1274
     1275        rc = exfat_fs_open(service_id, CACHE_MODE_WT, &rfn, &ridxp, info);
     1276        if (rc != EOK)
     1277                return rc;
     1278
     1279        exfat_fs_close(service_id, rfn);
     1280        return EOK;
    10791281}
    10801282
     
    10841286{
    10851287        int rc;
    1086         exfat_node_t *rootp = NULL, *bitmapp = NULL, *uctablep = NULL;
    10871288        enum cache_mode cmode;
    1088         exfat_bs_t *bs;
     1289        exfat_idx_t *ridxp;
     1290        fs_node_t *rfn;
    10891291
    10901292        /* Check for option enabling write through. */
     
    10941296                cmode = CACHE_MODE_WB;
    10951297
    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        
     1298        rc = exfat_fs_open(service_id, cmode, &rfn, &ridxp, NULL);
     1299        if (rc != EOK)
     1300                return rc;
     1301
     1302        *index = ridxp->index;
     1303        *size = EXFAT_NODE(rfn)->size;
     1304
    12621305        return EOK;
    12631306}
     
    12651308static int exfat_unmounted(service_id_t service_id)
    12661309{
    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 
     1310        fs_node_t *rfn;
     1311        int rc;
     1312
     1313        rc = exfat_root_get(&rfn, service_id);
     1314        if (rc != EOK)
     1315                return rc;
     1316
     1317        exfat_fs_close(service_id, rfn);
    13011318        return EOK;
    13021319}
     
    13631380                        return ENOTSUP;
    13641381                }
    1365                        
     1382
    13661383                aoff64_t spos = pos;
    13671384                char name[EXFAT_FILENAME_LEN + 1];
Note: See TracChangeset for help on using the changeset viewer.