source: mainline/uspace/srv/fs/exfat/exfat_ops.c@ a86e4f8

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a86e4f8 was a86e4f8, checked in by Oleg Romanenko <romanenko.oleg@…>, 14 years ago

exFAT:

  1. new function exfat_node_get_new_by_pos
  2. exFAT server correctly instantiating bitmap and uc-table nodes while

mounting.

  • Property mode set to 100644
File size: 20.0 KB
RevLine 
[db9aa04e]1/*
2 * Copyright (c) 2008 Jakub Jermar
3 * Copyright (c) 2011 Oleg Romanenko
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup fs
31 * @{
32 */
33
34/**
35 * @file exfat_ops.c
36 * @brief Implementation of VFS operations for the exFAT file system server.
37 */
38
39#include "exfat.h"
[4c3c4a5]40#include "exfat_fat.h"
[81d773f]41#include "exfat_dentry.h"
[a86e4f8]42#include "exfat_directory.h"
[db9aa04e]43#include "../../vfs/vfs.h"
44#include <libfs.h>
45#include <libblock.h>
46#include <ipc/services.h>
47#include <ipc/devmap.h>
48#include <macros.h>
49#include <async.h>
50#include <errno.h>
51#include <str.h>
52#include <byteorder.h>
53#include <adt/hash_table.h>
54#include <adt/list.h>
55#include <assert.h>
56#include <fibril_synch.h>
57#include <sys/mman.h>
58#include <align.h>
59#include <malloc.h>
[4c3c4a5]60#include <stdio.h>
[db9aa04e]61
[4c3c4a5]62#define EXFAT_NODE(node) ((node) ? (exfat_node_t *) (node)->data : NULL)
63#define FS_NODE(node) ((node) ? (node)->bp : NULL)
64
65
66/** Mutex protecting the list of cached free FAT nodes. */
67static FIBRIL_MUTEX_INITIALIZE(ffn_mutex);
68
69/** List of cached free FAT nodes. */
70static LIST_INITIALIZE(ffn_head);
[6d57e1c]71
72/*
[4c3c4a5]73 * Forward declarations of FAT libfs operations.
74 */
[81d773f]75/*
76static int exfat_bitmap_get(fs_node_t **, devmap_handle_t);
77static int exfat_uctable_get(fs_node_t **, devmap_handle_t);
78*/
[4c3c4a5]79static int exfat_root_get(fs_node_t **, devmap_handle_t);
80static int exfat_match(fs_node_t **, fs_node_t *, const char *);
81static int exfat_node_get(fs_node_t **, devmap_handle_t, fs_index_t);
82static int exfat_node_open(fs_node_t *);
83static int exfat_node_put(fs_node_t *);
84static int exfat_create_node(fs_node_t **, devmap_handle_t, int);
85static int exfat_destroy_node(fs_node_t *);
86static int exfat_link(fs_node_t *, fs_node_t *, const char *);
87static int exfat_unlink(fs_node_t *, fs_node_t *, const char *);
88static int exfat_has_children(bool *, fs_node_t *);
89static fs_index_t exfat_index_get(fs_node_t *);
90static aoff64_t exfat_size_get(fs_node_t *);
91static unsigned exfat_lnkcnt_get(fs_node_t *);
92static char exfat_plb_get_char(unsigned);
93static bool exfat_is_directory(fs_node_t *);
94static bool exfat_is_file(fs_node_t *node);
95static devmap_handle_t exfat_device_get(fs_node_t *node);
96
97/*
98 * Helper functions.
99 */
100static void exfat_node_initialize(exfat_node_t *node)
101{
102 fibril_mutex_initialize(&node->lock);
103 node->bp = NULL;
104 node->idx = NULL;
[81d773f]105 node->type = EXFAT_UNKNOW;
[4c3c4a5]106 link_initialize(&node->ffn_link);
107 node->size = 0;
108 node->lnkcnt = 0;
109 node->refcnt = 0;
110 node->dirty = false;
[81d773f]111 node->fragmented = true;
[4c3c4a5]112 node->lastc_cached_valid = false;
113 node->lastc_cached_value = 0;
114 node->currc_cached_valid = false;
115 node->currc_cached_bn = 0;
116 node->currc_cached_value = 0;
117}
118
119static int exfat_node_sync(exfat_node_t *node)
120{
121 return EOK;
122}
123
124static int exfat_node_fini_by_devmap_handle(devmap_handle_t devmap_handle)
125{
126 link_t *lnk;
127 exfat_node_t *nodep;
128 int rc;
129
130 /*
131 * We are called from fat_unmounted() and assume that there are already
132 * no nodes belonging to this instance with non-zero refcount. Therefore
133 * it is sufficient to clean up only the FAT free node list.
134 */
135
136restart:
137 fibril_mutex_lock(&ffn_mutex);
138 for (lnk = ffn_head.next; lnk != &ffn_head; lnk = lnk->next) {
139 nodep = list_get_instance(lnk, exfat_node_t, ffn_link);
140 if (!fibril_mutex_trylock(&nodep->lock)) {
141 fibril_mutex_unlock(&ffn_mutex);
142 goto restart;
143 }
144 if (!fibril_mutex_trylock(&nodep->idx->lock)) {
145 fibril_mutex_unlock(&nodep->lock);
146 fibril_mutex_unlock(&ffn_mutex);
147 goto restart;
148 }
149 if (nodep->idx->devmap_handle != devmap_handle) {
150 fibril_mutex_unlock(&nodep->idx->lock);
151 fibril_mutex_unlock(&nodep->lock);
152 continue;
153 }
154
155 list_remove(&nodep->ffn_link);
156 fibril_mutex_unlock(&ffn_mutex);
157
158 /*
159 * We can unlock the node and its index structure because we are
160 * the last player on this playground and VFS is preventing new
161 * players from entering.
162 */
163 fibril_mutex_unlock(&nodep->idx->lock);
164 fibril_mutex_unlock(&nodep->lock);
165
166 if (nodep->dirty) {
167 rc = exfat_node_sync(nodep);
168 if (rc != EOK)
169 return rc;
170 }
171 nodep->idx->nodep = NULL;
172 free(nodep->bp);
173 free(nodep);
174
175 /* Need to restart because we changed the ffn_head list. */
176 goto restart;
177 }
178 fibril_mutex_unlock(&ffn_mutex);
179
180 return EOK;
181}
182
[81d773f]183static int exfat_node_get_new(exfat_node_t **nodepp)
184{
185 fs_node_t *fn;
186 exfat_node_t *nodep;
187 int rc;
188
189 fibril_mutex_lock(&ffn_mutex);
190 if (!list_empty(&ffn_head)) {
191 /* Try to use a cached free node structure. */
192 exfat_idx_t *idxp_tmp;
193 nodep = list_get_instance(ffn_head.next, exfat_node_t, ffn_link);
194 if (!fibril_mutex_trylock(&nodep->lock))
195 goto skip_cache;
196 idxp_tmp = nodep->idx;
197 if (!fibril_mutex_trylock(&idxp_tmp->lock)) {
198 fibril_mutex_unlock(&nodep->lock);
199 goto skip_cache;
200 }
201 list_remove(&nodep->ffn_link);
202 fibril_mutex_unlock(&ffn_mutex);
203 if (nodep->dirty) {
204 rc = exfat_node_sync(nodep);
205 if (rc != EOK) {
206 idxp_tmp->nodep = NULL;
207 fibril_mutex_unlock(&nodep->lock);
208 fibril_mutex_unlock(&idxp_tmp->lock);
209 free(nodep->bp);
210 free(nodep);
211 return rc;
212 }
213 }
214 idxp_tmp->nodep = NULL;
215 fibril_mutex_unlock(&nodep->lock);
216 fibril_mutex_unlock(&idxp_tmp->lock);
217 fn = FS_NODE(nodep);
218 } else {
219skip_cache:
220 /* Try to allocate a new node structure. */
221 fibril_mutex_unlock(&ffn_mutex);
222 fn = (fs_node_t *)malloc(sizeof(fs_node_t));
223 if (!fn)
224 return ENOMEM;
225 nodep = (exfat_node_t *)malloc(sizeof(exfat_node_t));
226 if (!nodep) {
227 free(fn);
228 return ENOMEM;
229 }
230 }
231 exfat_node_initialize(nodep);
232 fs_node_initialize(fn);
233 fn->data = nodep;
234 nodep->bp = fn;
235
236 *nodepp = nodep;
237 return EOK;
238}
239
[a86e4f8]240static int exfat_node_get_new_by_pos(exfat_node_t **nodepp,
241 devmap_handle_t devmap_handle, exfat_cluster_t pfc, unsigned pdi)
242{
243 exfat_idx_t *idxp = exfat_idx_get_by_pos(devmap_handle, pfc, pdi);
244 if (!idxp)
245 return ENOMEM;
246 if (exfat_node_get_new(nodepp) != EOK)
247 return ENOMEM;
248 (*nodepp)->idx = idxp;
249 idxp->nodep = *nodepp;
250 return EOK;
251}
252
253
[81d773f]254/** Internal version of exfat_node_get().
255 *
256 * @param idxp Locked index structure.
257 */
258static int exfat_node_get_core(exfat_node_t **nodepp, exfat_idx_t *idxp)
259{
260 block_t *b=NULL;
261 //exfat_bs_t *bs;
262 //exfat_dentry_t *d;
263 exfat_node_t *nodep = NULL;
264 int rc;
265
266 if (idxp->nodep) {
267 /*
268 * We are lucky.
269 * The node is already instantiated in memory.
270 */
271 fibril_mutex_lock(&idxp->nodep->lock);
272 if (!idxp->nodep->refcnt++) {
273 fibril_mutex_lock(&ffn_mutex);
274 list_remove(&idxp->nodep->ffn_link);
275 fibril_mutex_unlock(&ffn_mutex);
276 }
277 fibril_mutex_unlock(&idxp->nodep->lock);
278 *nodepp = idxp->nodep;
279 return EOK;
280 }
281
282 /*
283 * We must instantiate the node from the file system.
284 */
285
286 assert(idxp->pfc);
287
288 rc = exfat_node_get_new(&nodep);
289 if (rc != EOK)
290 return rc;
291
292 //bs = block_bb_get(idxp->devmap_handle);
293
294 /* Access to exFAT directory and read two entries:
295 * file entry and stream entry
296 */
297 /*
298 exfat_directory_t di;
299 exfat_dentry_t *de;
300 exfat_directory_open(&di, ???);
301 exfat_directory_seek(&di, idxp->pdi);
302 exfat_directory_get(&di, &de);
303
304 switch (exfat_classify_dentry(de)) {
305 case EXFAT_DENTRY_FILE:
306 nodep->type = (de->file.attr & EXFAT_ATTR_SUBDIR)?
307 EXFAT_DIRECTORY : EXFAT_FILE;
308 exfat_directory_next(&di);
309 exfat_directory_get(&di, &de);
310 nodep->firtsc = de->stream.firstc;
311 nodep->size = de->stream.data_size;
312 nodep->fragmented = (de->stream.flags & 0x02) == 0;
313 break;
314 case EXFAT_DENTRY_BITMAP:
315 nodep->type = EXFAT_BITMAP;
316 nodep->firstc = de->bitmap.firstc;
317 nodep->size = de->bitmap.size;
318 nodep->fragmented = false;
319 break;
320 case EXFAT_DENTRY_UCTABLE:
321 nodep->type = EXFAT_UCTABLE;
322 nodep->firstc = de->uctable.firstc;
323 nodep->size = de->uctable.size;
324 nodep->fragmented = false;
325 break;
326 default:
327 case EXFAT_DENTRY_SKIP:
328 case EXFAT_DENTRY_LAST:
329 case EXFAT_DENTRY_FREE:
330 case EXFAT_DENTRY_VOLLABEL:
331 case EXFAT_DENTRY_GUID:
332 case EXFAT_DENTRY_STREAM:
333 case EXFAT_DENTRY_NAME:
334 (void) block_put(b);
335 (void) fat_node_put(FS_NODE(nodep));
336 return ENOENT;
337 }
338 */
339
340 /* Read the block that contains the dentry of interest. */
341 /*
342 rc = _fat_block_get(&b, bs, idxp->devmap_handle, idxp->pfc, NULL,
343 (idxp->pdi * sizeof(fat_dentry_t)) / BPS(bs), BLOCK_FLAGS_NONE);
344 if (rc != EOK) {
345 (void) fat_node_put(FS_NODE(nodep));
346 return rc;
347 }
348
349 d = ((fat_dentry_t *)b->data) + (idxp->pdi % DPS(bs));
350 */
351
352 nodep->lnkcnt = 1;
353 nodep->refcnt = 1;
354
355 rc = block_put(b);
356 if (rc != EOK) {
357 (void) exfat_node_put(FS_NODE(nodep));
358 return rc;
359 }
360
361 /* Link the idx structure with the node structure. */
362 nodep->idx = idxp;
363 idxp->nodep = nodep;
364
365 *nodepp = nodep;
366 return EOK;
367}
368
369
[4c3c4a5]370
371/*
[81d773f]372 * EXFAT libfs operations.
[4c3c4a5]373 */
374
375int exfat_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
376{
[81d773f]377 return exfat_node_get(rfn, devmap_handle, EXFAT_ROOT_IDX);
378}
379
380/*
381int exfat_bitmap_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
382{
383 return exfat_node_get(rfn, devmap_handle, EXFAT_BITMAP_IDX);
384}
[a86e4f8]385*/
386/*
[81d773f]387int exfat_uctable_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
388{
389 return exfat_node_get(rfn, devmap_handle, EXFAT_UCTABLE_IDX);
[4c3c4a5]390}
[81d773f]391*/
[4c3c4a5]392
393int exfat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
394{
395 *rfn = NULL;
396 return EOK;
397}
398
399/** Instantiate a exFAT in-core node. */
400int exfat_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)
401{
[81d773f]402 exfat_node_t *nodep;
403 exfat_idx_t *idxp;
404 int rc;
405
406 idxp = exfat_idx_get_by_index(devmap_handle, index);
407 if (!idxp) {
408 *rfn = NULL;
409 return EOK;
410 }
411 /* idxp->lock held */
412 rc = exfat_node_get_core(&nodep, idxp);
413 fibril_mutex_unlock(&idxp->lock);
414 if (rc == EOK)
415 *rfn = FS_NODE(nodep);
416 return rc;
[4c3c4a5]417}
418
419int exfat_node_open(fs_node_t *fn)
420{
421 /*
422 * Opening a file is stateless, nothing
423 * to be done here.
424 */
425 return EOK;
426}
427
428int exfat_node_put(fs_node_t *fn)
429{
430 return EOK;
431}
432
433int exfat_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int flags)
434{
435 *rfn = NULL;
436 return EOK;
437}
438
439int exfat_destroy_node(fs_node_t *fn)
440{
441 return EOK;
442}
443
444int exfat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
445{
446 return EOK;
447}
448
449int exfat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
450{
451 return EOK;
452}
453
454int exfat_has_children(bool *has_children, fs_node_t *fn)
455{
456 *has_children = false;
457 return EOK;
458}
459
460
461fs_index_t exfat_index_get(fs_node_t *fn)
462{
463 return EXFAT_NODE(fn)->idx->index;
464}
465
466aoff64_t exfat_size_get(fs_node_t *fn)
467{
468 return EXFAT_NODE(fn)->size;
469}
470
471unsigned exfat_lnkcnt_get(fs_node_t *fn)
472{
473 return EXFAT_NODE(fn)->lnkcnt;
474}
475
476char exfat_plb_get_char(unsigned pos)
477{
478 return exfat_reg.plb_ro[pos % PLB_SIZE];
479}
480
481bool exfat_is_directory(fs_node_t *fn)
482{
483 return EXFAT_NODE(fn)->type == EXFAT_DIRECTORY;
484}
485
486bool exfat_is_file(fs_node_t *fn)
487{
488 return EXFAT_NODE(fn)->type == EXFAT_FILE;
489}
490
491devmap_handle_t exfat_device_get(fs_node_t *node)
492{
493 return 0;
494}
495
496
497/** libfs operations */
[6d57e1c]498libfs_ops_t exfat_libfs_ops = {
499 .root_get = exfat_root_get,
500 .match = exfat_match,
501 .node_get = exfat_node_get,
502 .node_open = exfat_node_open,
503 .node_put = exfat_node_put,
504 .create = exfat_create_node,
505 .destroy = exfat_destroy_node,
506 .link = exfat_link,
507 .unlink = exfat_unlink,
508 .has_children = exfat_has_children,
509 .index_get = exfat_index_get,
510 .size_get = exfat_size_get,
511 .lnkcnt_get = exfat_lnkcnt_get,
512 .plb_get_char = exfat_plb_get_char,
513 .is_directory = exfat_is_directory,
514 .is_file = exfat_is_file,
515 .device_get = exfat_device_get
516};
[4c3c4a5]517
[6d57e1c]518
519/*
520 * VFS operations.
521 */
522
[a86e4f8]523/* Print debug info */
524static void exfat_fsinfo(exfat_bs_t *bs, devmap_handle_t devmap_handle)
525{
526 printf("exFAT file system mounted\n");
527 printf("Version: %d.%d\n", bs->version.major, bs->version.minor);
528 printf("Volume serial: %d\n", uint32_t_le2host(bs->volume_serial));
529 printf("Volume first sector: %lld\n", VOL_FS(bs));
530 printf("Volume sectors: %lld\n", VOL_CNT(bs));
531 printf("FAT first sector: %d\n", FAT_FS(bs));
532 printf("FAT sectors: %d\n", FAT_CNT(bs));
533 printf("Data first sector: %d\n", DATA_FS(bs));
534 printf("Data sectors: %d\n", DATA_CNT(bs));
535 printf("Root dir first cluster: %d\n", ROOT_FC(bs));
536 printf("Bytes per sector: %d\n", BPS(bs));
537 printf("Sectors per cluster: %d\n", SPC(bs));
538 printf("KBytes per cluster: %d\n", SPC(bs)*BPS(bs)/1024);
539
540 int i, rc;
541 exfat_cluster_t clst;
542 for (i=0; i<6; i++) {
543 rc = fat_get_cluster(bs, devmap_handle, i, &clst);
544 if (rc != EOK)
545 return;
546 printf("Clst %d: %x\n", i, clst);
547 }
548}
549
[6d57e1c]550void exfat_mounted(ipc_callid_t rid, ipc_call_t *request)
551{
552 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
[a86e4f8]553 exfat_node_t *rootp=NULL, *bitmapp=NULL, *uctablep=NULL;
[6d57e1c]554 enum cache_mode cmode;
555 exfat_bs_t *bs;
556
557 /* Accept the mount options */
558 char *opts;
559 int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
560
561 if (rc != EOK) {
562 async_answer_0(rid, rc);
563 return;
564 }
565
566 /* Check for option enabling write through. */
567 if (str_cmp(opts, "wtcache") == 0)
568 cmode = CACHE_MODE_WT;
569 else
570 cmode = CACHE_MODE_WB;
571
572 free(opts);
573
574 /* initialize libblock */
575 rc = block_init(devmap_handle, BS_SIZE);
576 if (rc != EOK) {
577 async_answer_0(rid, rc);
578 return;
579 }
580
581 /* prepare the boot block */
582 rc = block_bb_read(devmap_handle, BS_BLOCK);
583 if (rc != EOK) {
584 block_fini(devmap_handle);
585 async_answer_0(rid, rc);
586 return;
587 }
588
589 /* get the buffer with the boot sector */
590 bs = block_bb_get(devmap_handle);
591
592 /* Initialize the block cache */
[a86e4f8]593 rc = block_cache_init(devmap_handle, BPS(bs), 0 /* XXX */, cmode);
[6d57e1c]594 if (rc != EOK) {
595 block_fini(devmap_handle);
596 async_answer_0(rid, rc);
597 return;
598 }
599
[4c3c4a5]600 /* Do some simple sanity checks on the file system. */
601 rc = exfat_sanity_check(bs, devmap_handle);
602 if (rc != EOK) {
603 (void) block_cache_fini(devmap_handle);
604 block_fini(devmap_handle);
605 async_answer_0(rid, rc);
606 return;
607 }
608
609 rc = exfat_idx_init_by_devmap_handle(devmap_handle);
610 if (rc != EOK) {
611 (void) block_cache_fini(devmap_handle);
612 block_fini(devmap_handle);
613 async_answer_0(rid, rc);
614 return;
615 }
616
617 /* Initialize the root node. */
[a86e4f8]618 rc = exfat_node_get_new_by_pos(&rootp, devmap_handle, EXFAT_ROOT_PAR,
619 EXFAT_ROOT_POS);
620 if (rc!=EOK) {
[4c3c4a5]621 (void) block_cache_fini(devmap_handle);
622 block_fini(devmap_handle);
623 exfat_idx_fini_by_devmap_handle(devmap_handle);
624 async_answer_0(rid, ENOMEM);
625 return;
626 }
[a86e4f8]627 assert(rootp->idx->index == EXFAT_ROOT_IDX);
628
629 rootp->type = EXFAT_DIRECTORY;
630 rootp->firstc = ROOT_FC(bs);
631 rootp->fragmented = true;
632 rootp->refcnt = 1;
633 rootp->lnkcnt = 0; /* FS root is not linked */
[4c3c4a5]634
[a86e4f8]635 uint32_t clusters;
636 rc = fat_clusters_get(&clusters, bs, devmap_handle, rootp->firstc);
637 if (rc != EOK) {
638 free(rootp);
[4c3c4a5]639 (void) block_cache_fini(devmap_handle);
640 block_fini(devmap_handle);
641 exfat_idx_fini_by_devmap_handle(devmap_handle);
[a86e4f8]642 async_answer_0(rid, ENOTSUP);
[4c3c4a5]643 return;
644 }
[a86e4f8]645 rootp->size = BPS(bs) * SPC(bs) * clusters;
646 fibril_mutex_unlock(&rootp->idx->lock);
[4c3c4a5]647
[a86e4f8]648 /* Open root directory and looking for Bitmap and UC-Table */
649 exfat_directory_t di;
650 exfat_dentry_t *de;
651 rc = exfat_directory_open(rootp, &di);
652 if (rc != EOK) {
653 free(rootp);
654 (void) block_cache_fini(devmap_handle);
655 block_fini(devmap_handle);
656 exfat_idx_fini_by_devmap_handle(devmap_handle);
657 async_answer_0(rid, ENOTSUP);
658 return;
659 }
[4c3c4a5]660
[a86e4f8]661 /* Initialize the bitmap node. */
662 rc = exfat_directory_find(&di, EXFAT_DENTRY_BITMAP, &de);
663 if (rc != EOK) {
664 free(rootp);
665 (void) block_cache_fini(devmap_handle);
666 block_fini(devmap_handle);
667 exfat_idx_fini_by_devmap_handle(devmap_handle);
668 async_answer_0(rid, ENOTSUP);
669 return;
670 }
671
672 rc = exfat_node_get_new_by_pos(&bitmapp, devmap_handle, rootp->firstc,
673 di.pos);
674 if (rc!=EOK) {
[4c3c4a5]675 free(rootp);
676 (void) block_cache_fini(devmap_handle);
677 block_fini(devmap_handle);
678 exfat_idx_fini_by_devmap_handle(devmap_handle);
679 async_answer_0(rid, ENOMEM);
680 return;
681 }
[a86e4f8]682 assert(bitmapp->idx->index == EXFAT_BITMAP_IDX);
683 fibril_mutex_unlock(&bitmapp->idx->lock);
684
685 bitmapp->type = EXFAT_BITMAP;
686 bitmapp->firstc = de->bitmap.firstc;
687 bitmapp->fragmented = true;
688 bitmapp->refcnt = 1;
689 bitmapp->lnkcnt = 0;
690 bitmapp->size = de->bitmap.size;
691
692 /* Initialize the uctable node. */
693 rc = exfat_directory_seek(&di, 0);
694 if (rc != EOK) {
695 free(rootp);
696 free(bitmapp);
697 (void) block_cache_fini(devmap_handle);
698 block_fini(devmap_handle);
699 exfat_idx_fini_by_devmap_handle(devmap_handle);
700 async_answer_0(rid, ENOTSUP);
701 return;
702 }
[4c3c4a5]703
[a86e4f8]704 rc = exfat_directory_find(&di, EXFAT_DENTRY_UCTABLE, &de);
705 if (rc != EOK) {
706 free(rootp);
707 free(bitmapp);
708 (void) block_cache_fini(devmap_handle);
709 block_fini(devmap_handle);
710 exfat_idx_fini_by_devmap_handle(devmap_handle);
711 async_answer_0(rid, ENOTSUP);
712 return;
713 }
[4c3c4a5]714
[a86e4f8]715 rc = exfat_node_get_new_by_pos(&uctablep, devmap_handle, rootp->firstc,
716 di.pos);
717 if (rc!=EOK) {
718 free(rootp);
719 free(bitmapp);
720 (void) block_cache_fini(devmap_handle);
721 block_fini(devmap_handle);
722 exfat_idx_fini_by_devmap_handle(devmap_handle);
723 async_answer_0(rid, ENOMEM);
724 return;
725 }
726 assert(uctablep->idx->index == EXFAT_UCTABLE_IDX);
727 fibril_mutex_unlock(&uctablep->idx->lock);
728
729 uctablep->type = EXFAT_UCTABLE;
730 uctablep->firstc = de->uctable.firstc;
731 uctablep->fragmented = true;
732 uctablep->refcnt = 1;
733 uctablep->lnkcnt = 0;
734 uctablep->size = de->uctable.size;
735
736 rc = exfat_directory_close(&di);
737 if (rc!=EOK) {
738 free(rootp);
739 free(bitmapp);
740 free(uctablep);
741 (void) block_cache_fini(devmap_handle);
742 block_fini(devmap_handle);
743 exfat_idx_fini_by_devmap_handle(devmap_handle);
744 async_answer_0(rid, ENOMEM);
745 return;
746 }
747
748 exfat_fsinfo(bs, devmap_handle);
749 printf("Root dir size: %lld\n", rootp->size);
[4c3c4a5]750
[a86e4f8]751 async_answer_3(rid, EOK, rootp->idx->index, rootp->size, rootp->lnkcnt);
[6d57e1c]752}
753
754void exfat_mount(ipc_callid_t rid, ipc_call_t *request)
755{
756 libfs_mount(&exfat_libfs_ops, exfat_reg.fs_handle, rid, request);
757}
758
759void exfat_unmounted(ipc_callid_t rid, ipc_call_t *request)
760{
761 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
[4c3c4a5]762 fs_node_t *fn;
763 exfat_node_t *nodep;
764 int rc;
765
766 rc = exfat_root_get(&fn, devmap_handle);
767 if (rc != EOK) {
768 async_answer_0(rid, rc);
769 return;
770 }
771 nodep = EXFAT_NODE(fn);
772
773 /*
774 * We expect exactly two references on the root node. One for the
775 * fat_root_get() above and one created in fat_mounted().
776 */
777 if (nodep->refcnt != 2) {
778 (void) exfat_node_put(fn);
779 async_answer_0(rid, EBUSY);
780 return;
781 }
782
783 /*
784 * Put the root node and force it to the FAT free node list.
785 */
786 (void) exfat_node_put(fn);
787 (void) exfat_node_put(fn);
[6d57e1c]788
789 /*
790 * Perform cleanup of the node structures, index structures and
791 * associated data. Write back this file system's dirty blocks and
792 * stop using libblock for this instance.
793 */
[4c3c4a5]794 (void) exfat_node_fini_by_devmap_handle(devmap_handle);
795 exfat_idx_fini_by_devmap_handle(devmap_handle);
[6d57e1c]796 (void) block_cache_fini(devmap_handle);
797 block_fini(devmap_handle);
798
799 async_answer_0(rid, EOK);
800}
801
802void exfat_unmount(ipc_callid_t rid, ipc_call_t *request)
803{
804 libfs_unmount(&exfat_libfs_ops, rid, request);
805}
[db9aa04e]806
[a86e4f8]807/*
808int bitmap_is_allocated(exfat_bs_t *bs, devmap_handle_t devmap_handle,
809 exfat_cluster_t clst, bool *status)
810{
811 fs_node_t *fn;
812 exfat_node_t *bitmap;
813 int rc;
814
815 rc = exfat_bitmap_get(&fn, devmap_handle);
816 if (rc != EOK)
817 return rc;
818
819 nbitmap = EXFAT_NODE(fn);
820
821
822 return EOK;
823}
824*/
[db9aa04e]825
826/**
827 * @}
828 */
Note: See TracBrowser for help on using the repository browser.