source: mainline/uspace/srv/fs/exfat/exfat_bitmap.c

Last change on this file was 09ab0a9a, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix vertical spacing with new Ccheck revision.

  • Property mode set to 100644
File size: 6.5 KB
RevLine 
[5d5863c]1/*
2 * Copyright (c) 2011 Oleg Romanenko
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
[b1834a01]29/** @addtogroup exfat
[5d5863c]30 * @{
31 */
32
33/**
34 * @file exfat_bitmap.c
35 * @brief Functions that manipulate the Bitmap Table.
36 */
37
38#include "exfat_bitmap.h"
39#include "../../vfs/vfs.h"
40#include <libfs.h>
[f73b291]41#include <block.h>
[5d5863c]42#include <errno.h>
43#include <byteorder.h>
44#include <align.h>
45#include <assert.h>
46#include <fibril_synch.h>
47#include <mem.h>
48
[1b20da0]49errno_t exfat_bitmap_is_free(exfat_bs_t *bs, service_id_t service_id,
[5d5863c]50 exfat_cluster_t clst)
51{
[25c60f4]52 fs_node_t *fn;
[ff0c270]53 block_t *b = NULL;
[25c60f4]54 exfat_node_t *bitmapp;
55 uint8_t *bitmap;
[b7fd2a0]56 errno_t rc;
[25c60f4]57 bool alloc;
58
59 clst -= EXFAT_CLST_FIRST;
[a35b458]60
[375ab5e]61 rc = exfat_bitmap_get(&fn, service_id);
[25c60f4]62 if (rc != EOK)
63 return rc;
64 bitmapp = EXFAT_NODE(fn);
[a35b458]65
[25c60f4]66 aoff64_t offset = clst / 8;
67 rc = exfat_block_get(&b, bs, bitmapp, offset / BPS(bs), BLOCK_FLAGS_NONE);
68 if (rc != EOK) {
69 (void) exfat_node_put(fn);
70 return rc;
71 }
72 bitmap = (uint8_t *)b->data;
73 alloc = bitmap[offset % BPS(bs)] & (1 << (clst % 8));
74
75 rc = block_put(b);
76 if (rc != EOK) {
77 (void) exfat_node_put(fn);
78 return rc;
79 }
80 rc = exfat_node_put(fn);
81 if (rc != EOK)
82 return rc;
83
84 if (alloc)
85 return ENOENT;
86
[5d5863c]87 return EOK;
88}
89
[1b20da0]90errno_t exfat_bitmap_set_cluster(exfat_bs_t *bs, service_id_t service_id,
[25c60f4]91 exfat_cluster_t clst)
[5d5863c]92{
93 fs_node_t *fn;
[ff0c270]94 block_t *b = NULL;
[5d5863c]95 exfat_node_t *bitmapp;
96 uint8_t *bitmap;
[b7fd2a0]97 errno_t rc;
[5d5863c]98
[25c60f4]99 clst -= EXFAT_CLST_FIRST;
[a35b458]100
[375ab5e]101 rc = exfat_bitmap_get(&fn, service_id);
[5d5863c]102 if (rc != EOK)
103 return rc;
104 bitmapp = EXFAT_NODE(fn);
[a35b458]105
[25c60f4]106 aoff64_t offset = clst / 8;
[5d5863c]107 rc = exfat_block_get(&b, bs, bitmapp, offset / BPS(bs), BLOCK_FLAGS_NONE);
108 if (rc != EOK) {
109 (void) exfat_node_put(fn);
110 return rc;
111 }
112 bitmap = (uint8_t *)b->data;
[25c60f4]113 bitmap[offset % BPS(bs)] |= (1 << (clst % 8));
[5d5863c]114
115 b->dirty = true;
116 rc = block_put(b);
117 if (rc != EOK) {
118 (void) exfat_node_put(fn);
119 return rc;
120 }
[a35b458]121
[5d5863c]122 return exfat_node_put(fn);
123}
124
[1b20da0]125errno_t exfat_bitmap_clear_cluster(exfat_bs_t *bs, service_id_t service_id,
[25c60f4]126 exfat_cluster_t clst)
[5d5863c]127{
[25c60f4]128 fs_node_t *fn;
[ff0c270]129 block_t *b = NULL;
[25c60f4]130 exfat_node_t *bitmapp;
131 uint8_t *bitmap;
[b7fd2a0]132 errno_t rc;
[25c60f4]133
134 clst -= EXFAT_CLST_FIRST;
[a35b458]135
[375ab5e]136 rc = exfat_bitmap_get(&fn, service_id);
[25c60f4]137 if (rc != EOK)
138 return rc;
139 bitmapp = EXFAT_NODE(fn);
[a35b458]140
[25c60f4]141 aoff64_t offset = clst / 8;
[ff0c270]142 rc = exfat_block_get(&b, bs, bitmapp, offset / BPS(bs),
143 BLOCK_FLAGS_NONE);
[25c60f4]144 if (rc != EOK) {
145 (void) exfat_node_put(fn);
146 return rc;
147 }
148 bitmap = (uint8_t *)b->data;
149 bitmap[offset % BPS(bs)] &= ~(1 << (clst % 8));
150
151 b->dirty = true;
152 rc = block_put(b);
153 if (rc != EOK) {
154 (void) exfat_node_put(fn);
155 return rc;
156 }
[a35b458]157
[25c60f4]158 return exfat_node_put(fn);
[5d5863c]159}
160
[1b20da0]161errno_t exfat_bitmap_set_clusters(exfat_bs_t *bs, service_id_t service_id,
[5d5863c]162 exfat_cluster_t firstc, exfat_cluster_t count)
163{
[b7fd2a0]164 errno_t rc;
[5d5863c]165 exfat_cluster_t clst;
166 clst = firstc;
167
[1433ecda]168 while (clst < firstc + count) {
[e738d56]169 rc = exfat_bitmap_set_cluster(bs, service_id, clst);
[5d5863c]170 if (rc != EOK) {
[ff0c270]171 if (clst - firstc > 0)
[e738d56]172 (void) exfat_bitmap_clear_clusters(bs, service_id,
[ff0c270]173 firstc, clst - firstc);
[5d5863c]174 return rc;
175 }
176 clst++;
177 }
178 return EOK;
179}
180
[1b20da0]181errno_t exfat_bitmap_clear_clusters(exfat_bs_t *bs, service_id_t service_id,
[5d5863c]182 exfat_cluster_t firstc, exfat_cluster_t count)
183{
[b7fd2a0]184 errno_t rc;
[5d5863c]185 exfat_cluster_t clst;
186 clst = firstc;
187
[ff0c270]188 while (clst < firstc + count) {
[e738d56]189 rc = exfat_bitmap_clear_cluster(bs, service_id, clst);
[5d5863c]190 if (rc != EOK)
191 return rc;
192 clst++;
193 }
194 return EOK;
195}
196
[1b20da0]197errno_t exfat_bitmap_alloc_clusters(exfat_bs_t *bs, service_id_t service_id,
[5d5863c]198 exfat_cluster_t *firstc, exfat_cluster_t count)
199{
200 exfat_cluster_t startc, endc;
201 startc = EXFAT_CLST_FIRST;
202
[ff0c270]203 while (startc < DATA_CNT(bs) + 2) {
[e0d98b2]204 endc = startc;
[e738d56]205 while (exfat_bitmap_is_free(bs, service_id, endc) == EOK) {
[ff0c270]206 if ((endc - startc) + 1 == count) {
[e0d98b2]207 *firstc = startc;
[e738d56]208 return exfat_bitmap_set_clusters(bs, service_id, startc, count);
[ff0c270]209 } else
[e0d98b2]210 endc++;
211 }
[1433ecda]212 startc = endc + 1;
[5d5863c]213 }
214 return ENOSPC;
215}
216
[1b20da0]217errno_t exfat_bitmap_append_clusters(exfat_bs_t *bs, exfat_node_t *nodep,
[5d5863c]218 exfat_cluster_t count)
219{
220 if (nodep->firstc == 0) {
[1b20da0]221 return exfat_bitmap_alloc_clusters(bs, nodep->idx->service_id,
[5d5863c]222 &nodep->firstc, count);
223 } else {
224 exfat_cluster_t lastc, clst;
225 lastc = nodep->firstc + ROUND_UP(nodep->size, BPC(bs)) / BPC(bs) - 1;
226
[ff0c270]227 clst = lastc + 1;
[e738d56]228 while (exfat_bitmap_is_free(bs, nodep->idx->service_id, clst) == EOK) {
[1433ecda]229 if (clst - lastc == count) {
[1b20da0]230 return exfat_bitmap_set_clusters(bs, nodep->idx->service_id,
[ff0c270]231 lastc + 1, count);
232 } else
[5d5863c]233 clst++;
234 }
235 return ENOSPC;
236 }
237}
238
[1b20da0]239errno_t exfat_bitmap_free_clusters(exfat_bs_t *bs, exfat_node_t *nodep,
[5d5863c]240 exfat_cluster_t count)
241{
242 exfat_cluster_t lastc;
243 lastc = nodep->firstc + ROUND_UP(nodep->size, BPC(bs)) / BPC(bs) - 1;
244 lastc -= count;
245
[e738d56]246 return exfat_bitmap_clear_clusters(bs, nodep->idx->service_id, lastc + 1, count);
[5d5863c]247}
248
[b7fd2a0]249errno_t exfat_bitmap_replicate_clusters(exfat_bs_t *bs, exfat_node_t *nodep)
[5d5863c]250{
[b7fd2a0]251 errno_t rc;
[5d5863c]252 exfat_cluster_t lastc, clst;
[375ab5e]253 service_id_t service_id = nodep->idx->service_id;
[5d5863c]254 lastc = nodep->firstc + ROUND_UP(nodep->size, BPC(bs)) / BPC(bs) - 1;
255
256 for (clst = nodep->firstc; clst < lastc; clst++) {
[ff0c270]257 rc = exfat_set_cluster(bs, service_id, clst, clst + 1);
[5d5863c]258 if (rc != EOK)
259 return rc;
260 }
261
[375ab5e]262 return exfat_set_cluster(bs, service_id, lastc, EXFAT_CLST_EOF);
[5d5863c]263}
264
265/**
266 * @}
267 */
Note: See TracBrowser for help on using the repository browser.