source: mainline/uspace/srv/fs/exfat/exfat_bitmap.c@ 375ab5e

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

Merge from lp:~romanenko-oleg/helenos/fat.

  • Property mode set to 100644
File size: 6.3 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
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
[375ab5e]51int bitmap_is_free(exfat_bs_t *bs, service_id_t service_id,
[5d5863c]52 exfat_cluster_t clst)
53{
[25c60f4]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
[375ab5e]63 rc = exfat_bitmap_get(&fn, service_id);
[25c60f4]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
[5d5863c]89 return EOK;
90}
91
[375ab5e]92int bitmap_set_cluster(exfat_bs_t *bs, service_id_t service_id,
[25c60f4]93 exfat_cluster_t clst)
[5d5863c]94{
95 fs_node_t *fn;
96 block_t *b=NULL;
97 exfat_node_t *bitmapp;
98 uint8_t *bitmap;
99 int rc;
100
[25c60f4]101 clst -= EXFAT_CLST_FIRST;
[5d5863c]102
[375ab5e]103 rc = exfat_bitmap_get(&fn, service_id);
[5d5863c]104 if (rc != EOK)
105 return rc;
106 bitmapp = EXFAT_NODE(fn);
107
[25c60f4]108 aoff64_t offset = clst / 8;
[5d5863c]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;
[25c60f4]115 bitmap[offset % BPS(bs)] |= (1 << (clst % 8));
[5d5863c]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
[375ab5e]127int bitmap_clear_cluster(exfat_bs_t *bs, service_id_t service_id,
[25c60f4]128 exfat_cluster_t clst)
[5d5863c]129{
[25c60f4]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
[375ab5e]138 rc = exfat_bitmap_get(&fn, service_id);
[25c60f4]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), BLOCK_FLAGS_NONE);
145 if (rc != EOK) {
146 (void) exfat_node_put(fn);
147 return rc;
148 }
149 bitmap = (uint8_t *)b->data;
150 bitmap[offset % BPS(bs)] &= ~(1 << (clst % 8));
151
152 b->dirty = true;
153 rc = block_put(b);
154 if (rc != EOK) {
155 (void) exfat_node_put(fn);
156 return rc;
157 }
158
159 return exfat_node_put(fn);
[5d5863c]160}
161
[375ab5e]162int bitmap_set_clusters(exfat_bs_t *bs, service_id_t service_id,
[5d5863c]163 exfat_cluster_t firstc, exfat_cluster_t count)
164{
165 int rc;
166 exfat_cluster_t clst;
167 clst = firstc;
168
169 while (clst < firstc+count ) {
[375ab5e]170 rc = bitmap_set_cluster(bs, service_id, clst);
[5d5863c]171 if (rc != EOK) {
172 if ((clst-firstc) > 0)
[375ab5e]173 (void) bitmap_clear_clusters(bs, service_id, firstc, clst-firstc);
[5d5863c]174 return rc;
175 }
176 clst++;
177 }
178 return EOK;
179}
180
[375ab5e]181int bitmap_clear_clusters(exfat_bs_t *bs, service_id_t service_id,
[5d5863c]182 exfat_cluster_t firstc, exfat_cluster_t count)
183{
184 int rc;
185 exfat_cluster_t clst;
186 clst = firstc;
187
188 while (clst < firstc+count ) {
[375ab5e]189 rc = bitmap_clear_cluster(bs, service_id, clst);
[5d5863c]190 if (rc != EOK)
191 return rc;
192 clst++;
193 }
194 return EOK;
195}
196
[375ab5e]197int 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
203 while (startc < DATA_CNT(bs)+2) {
[e0d98b2]204 endc = startc;
[375ab5e]205 while (bitmap_is_free(bs, service_id, endc) == EOK) {
[e0d98b2]206 if ((endc - startc)+1 == count){
207 *firstc = startc;
[375ab5e]208 return bitmap_set_clusters(bs, service_id, startc, count);
[5d5863c]209 }
[e0d98b2]210 else
211 endc++;
212 }
213 startc = endc+1;
[5d5863c]214 }
215 return ENOSPC;
216}
217
218
219int bitmap_append_clusters(exfat_bs_t *bs, exfat_node_t *nodep,
220 exfat_cluster_t count)
221{
222 if (nodep->firstc == 0) {
[375ab5e]223 return bitmap_alloc_clusters(bs, nodep->idx->service_id,
[5d5863c]224 &nodep->firstc, count);
225 } else {
226 exfat_cluster_t lastc, clst;
227 lastc = nodep->firstc + ROUND_UP(nodep->size, BPC(bs)) / BPC(bs) - 1;
228
229 clst = lastc+1;
[375ab5e]230 while (bitmap_is_free(bs, nodep->idx->service_id, clst) == EOK) {
[5d5863c]231 if ((clst - lastc) == count){
[375ab5e]232 return bitmap_set_clusters(bs, nodep->idx->service_id,
[5d5863c]233 lastc+1, count);
234 }
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
[375ab5e]250 return bitmap_clear_clusters(bs, nodep->idx->service_id, lastc+1, count);
[5d5863c]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;
[375ab5e]258 service_id_t service_id = nodep->idx->service_id;
[5d5863c]259 lastc = nodep->firstc + ROUND_UP(nodep->size, BPC(bs)) / BPC(bs) - 1;
260
261 for (clst = nodep->firstc; clst < lastc; clst++) {
[375ab5e]262 rc = exfat_set_cluster(bs, service_id, clst, clst+1);
[5d5863c]263 if (rc != EOK)
264 return rc;
265 }
266
[375ab5e]267 return exfat_set_cluster(bs, service_id, lastc, EXFAT_CLST_EOF);
[5d5863c]268}
269
270
271
272/**
273 * @}
274 */
Note: See TracBrowser for help on using the repository browser.