source: mainline/uspace/srv/fs/exfat/exfat_bitmap.c@ 4bf6895

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4bf6895 was ff0c270, checked in by Jakub Jermar <jakub@…>, 14 years ago

Cstyle.

  • Property mode set to 100644
File size: 6.4 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 fs
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 <libblock.h>
42#include <errno.h>
43#include <byteorder.h>
44#include <align.h>
45#include <assert.h>
46#include <fibril_synch.h>
47#include <malloc.h>
48#include <mem.h>
49
50
51int bitmap_is_free(exfat_bs_t *bs, service_id_t service_id,
52 exfat_cluster_t clst)
53{
54 fs_node_t *fn;
55 block_t *b = NULL;
56 exfat_node_t *bitmapp;
57 uint8_t *bitmap;
58 int rc;
59 bool alloc;
60
61 clst -= EXFAT_CLST_FIRST;
62
63 rc = exfat_bitmap_get(&fn, service_id);
64 if (rc != EOK)
65 return rc;
66 bitmapp = EXFAT_NODE(fn);
67
68 aoff64_t offset = clst / 8;
69 rc = exfat_block_get(&b, bs, bitmapp, offset / BPS(bs), BLOCK_FLAGS_NONE);
70 if (rc != EOK) {
71 (void) exfat_node_put(fn);
72 return rc;
73 }
74 bitmap = (uint8_t *)b->data;
75 alloc = bitmap[offset % BPS(bs)] & (1 << (clst % 8));
76
77 rc = block_put(b);
78 if (rc != EOK) {
79 (void) exfat_node_put(fn);
80 return rc;
81 }
82 rc = exfat_node_put(fn);
83 if (rc != EOK)
84 return rc;
85
86 if (alloc)
87 return ENOENT;
88
89 return EOK;
90}
91
92int bitmap_set_cluster(exfat_bs_t *bs, service_id_t service_id,
93 exfat_cluster_t clst)
94{
95 fs_node_t *fn;
96 block_t *b = NULL;
97 exfat_node_t *bitmapp;
98 uint8_t *bitmap;
99 int rc;
100
101 clst -= EXFAT_CLST_FIRST;
102
103 rc = exfat_bitmap_get(&fn, service_id);
104 if (rc != EOK)
105 return rc;
106 bitmapp = EXFAT_NODE(fn);
107
108 aoff64_t offset = clst / 8;
109 rc = exfat_block_get(&b, bs, bitmapp, offset / BPS(bs), BLOCK_FLAGS_NONE);
110 if (rc != EOK) {
111 (void) exfat_node_put(fn);
112 return rc;
113 }
114 bitmap = (uint8_t *)b->data;
115 bitmap[offset % BPS(bs)] |= (1 << (clst % 8));
116
117 b->dirty = true;
118 rc = block_put(b);
119 if (rc != EOK) {
120 (void) exfat_node_put(fn);
121 return rc;
122 }
123
124 return exfat_node_put(fn);
125}
126
127int bitmap_clear_cluster(exfat_bs_t *bs, service_id_t service_id,
128 exfat_cluster_t clst)
129{
130 fs_node_t *fn;
131 block_t *b = NULL;
132 exfat_node_t *bitmapp;
133 uint8_t *bitmap;
134 int rc;
135
136 clst -= EXFAT_CLST_FIRST;
137
138 rc = exfat_bitmap_get(&fn, service_id);
139 if (rc != EOK)
140 return rc;
141 bitmapp = EXFAT_NODE(fn);
142
143 aoff64_t offset = clst / 8;
144 rc = exfat_block_get(&b, bs, bitmapp, offset / BPS(bs),
145 BLOCK_FLAGS_NONE);
146 if (rc != EOK) {
147 (void) exfat_node_put(fn);
148 return rc;
149 }
150 bitmap = (uint8_t *)b->data;
151 bitmap[offset % BPS(bs)] &= ~(1 << (clst % 8));
152
153 b->dirty = true;
154 rc = block_put(b);
155 if (rc != EOK) {
156 (void) exfat_node_put(fn);
157 return rc;
158 }
159
160 return exfat_node_put(fn);
161}
162
163int bitmap_set_clusters(exfat_bs_t *bs, service_id_t service_id,
164 exfat_cluster_t firstc, exfat_cluster_t count)
165{
166 int rc;
167 exfat_cluster_t clst;
168 clst = firstc;
169
170 while (clst < firstc + count ) {
171 rc = bitmap_set_cluster(bs, service_id, clst);
172 if (rc != EOK) {
173 if (clst - firstc > 0)
174 (void) bitmap_clear_clusters(bs, service_id,
175 firstc, clst - firstc);
176 return rc;
177 }
178 clst++;
179 }
180 return EOK;
181}
182
183int bitmap_clear_clusters(exfat_bs_t *bs, service_id_t service_id,
184 exfat_cluster_t firstc, exfat_cluster_t count)
185{
186 int rc;
187 exfat_cluster_t clst;
188 clst = firstc;
189
190 while (clst < firstc + count) {
191 rc = bitmap_clear_cluster(bs, service_id, clst);
192 if (rc != EOK)
193 return rc;
194 clst++;
195 }
196 return EOK;
197}
198
199int bitmap_alloc_clusters(exfat_bs_t *bs, service_id_t service_id,
200 exfat_cluster_t *firstc, exfat_cluster_t count)
201{
202 exfat_cluster_t startc, endc;
203 startc = EXFAT_CLST_FIRST;
204
205 while (startc < DATA_CNT(bs) + 2) {
206 endc = startc;
207 while (bitmap_is_free(bs, service_id, endc) == EOK) {
208 if ((endc - startc) + 1 == count) {
209 *firstc = startc;
210 return bitmap_set_clusters(bs, service_id, startc, count);
211 } else
212 endc++;
213 }
214 startc = endc+1;
215 }
216 return ENOSPC;
217}
218
219
220int bitmap_append_clusters(exfat_bs_t *bs, exfat_node_t *nodep,
221 exfat_cluster_t count)
222{
223 if (nodep->firstc == 0) {
224 return bitmap_alloc_clusters(bs, nodep->idx->service_id,
225 &nodep->firstc, count);
226 } else {
227 exfat_cluster_t lastc, clst;
228 lastc = nodep->firstc + ROUND_UP(nodep->size, BPC(bs)) / BPC(bs) - 1;
229
230 clst = lastc + 1;
231 while (bitmap_is_free(bs, nodep->idx->service_id, clst) == EOK) {
232 if (clst - lastc == count){
233 return bitmap_set_clusters(bs, nodep->idx->service_id,
234 lastc + 1, count);
235 } else
236 clst++;
237 }
238 return ENOSPC;
239 }
240}
241
242
243int bitmap_free_clusters(exfat_bs_t *bs, exfat_node_t *nodep,
244 exfat_cluster_t count)
245{
246 exfat_cluster_t lastc;
247 lastc = nodep->firstc + ROUND_UP(nodep->size, BPC(bs)) / BPC(bs) - 1;
248 lastc -= count;
249
250 return bitmap_clear_clusters(bs, nodep->idx->service_id, lastc + 1, count);
251}
252
253
254int bitmap_replicate_clusters(exfat_bs_t *bs, exfat_node_t *nodep)
255{
256 int rc;
257 exfat_cluster_t lastc, clst;
258 service_id_t service_id = nodep->idx->service_id;
259 lastc = nodep->firstc + ROUND_UP(nodep->size, BPC(bs)) / BPC(bs) - 1;
260
261 for (clst = nodep->firstc; clst < lastc; clst++) {
262 rc = exfat_set_cluster(bs, service_id, clst, clst + 1);
263 if (rc != EOK)
264 return rc;
265 }
266
267 return exfat_set_cluster(bs, service_id, lastc, EXFAT_CLST_EOF);
268}
269
270
271
272/**
273 * @}
274 */
Note: See TracBrowser for help on using the repository browser.