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
Line 
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
29/** @addtogroup exfat
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>
41#include <block.h>
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
49errno_t exfat_bitmap_is_free(exfat_bs_t *bs, service_id_t service_id,
50 exfat_cluster_t clst)
51{
52 fs_node_t *fn;
53 block_t *b = NULL;
54 exfat_node_t *bitmapp;
55 uint8_t *bitmap;
56 errno_t rc;
57 bool alloc;
58
59 clst -= EXFAT_CLST_FIRST;
60
61 rc = exfat_bitmap_get(&fn, service_id);
62 if (rc != EOK)
63 return rc;
64 bitmapp = EXFAT_NODE(fn);
65
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
87 return EOK;
88}
89
90errno_t exfat_bitmap_set_cluster(exfat_bs_t *bs, service_id_t service_id,
91 exfat_cluster_t clst)
92{
93 fs_node_t *fn;
94 block_t *b = NULL;
95 exfat_node_t *bitmapp;
96 uint8_t *bitmap;
97 errno_t rc;
98
99 clst -= EXFAT_CLST_FIRST;
100
101 rc = exfat_bitmap_get(&fn, service_id);
102 if (rc != EOK)
103 return rc;
104 bitmapp = EXFAT_NODE(fn);
105
106 aoff64_t offset = clst / 8;
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;
113 bitmap[offset % BPS(bs)] |= (1 << (clst % 8));
114
115 b->dirty = true;
116 rc = block_put(b);
117 if (rc != EOK) {
118 (void) exfat_node_put(fn);
119 return rc;
120 }
121
122 return exfat_node_put(fn);
123}
124
125errno_t exfat_bitmap_clear_cluster(exfat_bs_t *bs, service_id_t service_id,
126 exfat_cluster_t clst)
127{
128 fs_node_t *fn;
129 block_t *b = NULL;
130 exfat_node_t *bitmapp;
131 uint8_t *bitmap;
132 errno_t rc;
133
134 clst -= EXFAT_CLST_FIRST;
135
136 rc = exfat_bitmap_get(&fn, service_id);
137 if (rc != EOK)
138 return rc;
139 bitmapp = EXFAT_NODE(fn);
140
141 aoff64_t offset = clst / 8;
142 rc = exfat_block_get(&b, bs, bitmapp, offset / BPS(bs),
143 BLOCK_FLAGS_NONE);
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 }
157
158 return exfat_node_put(fn);
159}
160
161errno_t exfat_bitmap_set_clusters(exfat_bs_t *bs, service_id_t service_id,
162 exfat_cluster_t firstc, exfat_cluster_t count)
163{
164 errno_t rc;
165 exfat_cluster_t clst;
166 clst = firstc;
167
168 while (clst < firstc + count) {
169 rc = exfat_bitmap_set_cluster(bs, service_id, clst);
170 if (rc != EOK) {
171 if (clst - firstc > 0)
172 (void) exfat_bitmap_clear_clusters(bs, service_id,
173 firstc, clst - firstc);
174 return rc;
175 }
176 clst++;
177 }
178 return EOK;
179}
180
181errno_t exfat_bitmap_clear_clusters(exfat_bs_t *bs, service_id_t service_id,
182 exfat_cluster_t firstc, exfat_cluster_t count)
183{
184 errno_t rc;
185 exfat_cluster_t clst;
186 clst = firstc;
187
188 while (clst < firstc + count) {
189 rc = exfat_bitmap_clear_cluster(bs, service_id, clst);
190 if (rc != EOK)
191 return rc;
192 clst++;
193 }
194 return EOK;
195}
196
197errno_t exfat_bitmap_alloc_clusters(exfat_bs_t *bs, service_id_t service_id,
198 exfat_cluster_t *firstc, exfat_cluster_t count)
199{
200 exfat_cluster_t startc, endc;
201 startc = EXFAT_CLST_FIRST;
202
203 while (startc < DATA_CNT(bs) + 2) {
204 endc = startc;
205 while (exfat_bitmap_is_free(bs, service_id, endc) == EOK) {
206 if ((endc - startc) + 1 == count) {
207 *firstc = startc;
208 return exfat_bitmap_set_clusters(bs, service_id, startc, count);
209 } else
210 endc++;
211 }
212 startc = endc + 1;
213 }
214 return ENOSPC;
215}
216
217errno_t exfat_bitmap_append_clusters(exfat_bs_t *bs, exfat_node_t *nodep,
218 exfat_cluster_t count)
219{
220 if (nodep->firstc == 0) {
221 return exfat_bitmap_alloc_clusters(bs, nodep->idx->service_id,
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
227 clst = lastc + 1;
228 while (exfat_bitmap_is_free(bs, nodep->idx->service_id, clst) == EOK) {
229 if (clst - lastc == count) {
230 return exfat_bitmap_set_clusters(bs, nodep->idx->service_id,
231 lastc + 1, count);
232 } else
233 clst++;
234 }
235 return ENOSPC;
236 }
237}
238
239errno_t exfat_bitmap_free_clusters(exfat_bs_t *bs, exfat_node_t *nodep,
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
246 return exfat_bitmap_clear_clusters(bs, nodep->idx->service_id, lastc + 1, count);
247}
248
249errno_t exfat_bitmap_replicate_clusters(exfat_bs_t *bs, exfat_node_t *nodep)
250{
251 errno_t rc;
252 exfat_cluster_t lastc, clst;
253 service_id_t service_id = nodep->idx->service_id;
254 lastc = nodep->firstc + ROUND_UP(nodep->size, BPC(bs)) / BPC(bs) - 1;
255
256 for (clst = nodep->firstc; clst < lastc; clst++) {
257 rc = exfat_set_cluster(bs, service_id, clst, clst + 1);
258 if (rc != EOK)
259 return rc;
260 }
261
262 return exfat_set_cluster(bs, service_id, lastc, EXFAT_CLST_EOF);
263}
264
265/**
266 * @}
267 */
Note: See TracBrowser for help on using the repository browser.