]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - repair/bmap.c
2 * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
34 #include "err_protos.h"
38 * Block mapping code taken from xfs_db.
42 * Append an extent to the block entry.
55 size
= BLKENT_SIZE(c
+ ent
->nblks
);
56 if ((*entp
= ent
= realloc(ent
, size
)) == NULL
) {
57 do_warn("realloc failed in blkent_append (%u bytes)\n", size
);
60 for (i
= 0; i
< c
; i
++)
61 ent
->blks
[ent
->nblks
+ i
] = b
+ i
;
66 * Make a new block entry.
77 if ((ent
= malloc(BLKENT_SIZE(c
))) == NULL
) {
78 do_warn("malloc failed in blkent_new (%u bytes)\n",
84 for (i
= 0; i
< c
; i
++)
90 * Prepend an extent to the block entry.
103 if ((newent
= malloc(BLKENT_SIZE(oldent
->nblks
+ c
))) == NULL
) {
104 do_warn("malloc failed in blkent_prepend (%u bytes)\n",
105 BLKENT_SIZE(oldent
->nblks
+ c
));
109 newent
->nblks
= oldent
->nblks
+ c
;
110 newent
->startoff
= oldent
->startoff
- c
;
111 for (i
= 0; i
< c
; i
++)
112 newent
->blks
[i
] = b
+ c
;
113 for (; i
< oldent
->nblks
+ c
; i
++)
114 newent
->blks
[i
] = oldent
->blks
[i
- c
];
120 * Allocate a block map.
130 if ((blkmap
= malloc(BLKMAP_SIZE(nex
))) == NULL
) {
131 do_warn("malloc failed in blkmap_alloc (%u bytes)\n",
135 blkmap
->naents
= nex
;
152 for (i
= 0, entp
= blkmap
->ents
; i
< blkmap
->nents
; i
++, entp
++)
158 * Get one entry from a block map.
169 for (i
= 0, entp
= blkmap
->ents
; i
< blkmap
->nents
; i
++, entp
++) {
171 if (o
>= ent
->startoff
&& o
< ent
->startoff
+ ent
->nblks
)
172 return ent
->blks
[o
- ent
->startoff
];
178 * Get a chunk of entries from a block map.
194 for (i
= nex
= 0, bmp
= NULL
, entp
= blkmap
->ents
;
198 if (ent
->startoff
>= o
+ nb
)
200 if (ent
->startoff
+ ent
->nblks
<= o
)
202 for (ento
= ent
->startoff
;
203 ento
< ent
->startoff
+ ent
->nblks
&& ento
< o
+ nb
;
208 bmp
[nex
- 1].startoff
+ bmp
[nex
- 1].blockcount
==
210 bmp
[nex
- 1].startblock
+ bmp
[nex
- 1].blockcount
==
211 ent
->blks
[ento
- ent
->startoff
])
212 bmp
[nex
- 1].blockcount
++;
214 bmp
= realloc(bmp
, ++nex
* sizeof(*bmp
));
216 do_warn("realloc failed in blkmap_getn"
221 bmp
[nex
- 1].startoff
= ento
;
222 bmp
[nex
- 1].startblock
=
223 ent
->blks
[ento
- ent
->startoff
];
224 bmp
[nex
- 1].blockcount
= 1;
225 bmp
[nex
- 1].flag
= 0;
234 * Make a block map larger.
248 idx
= (int)(entp
- blkmap
->ents
);
249 if (blkmap
->naents
== blkmap
->nents
) {
250 size
= BLKMAP_SIZE(blkmap
->nents
+ 1);
251 if ((*blkmapp
= blkmap
= realloc(blkmap
, size
)) == NULL
) {
252 do_warn("realloc failed in blkmap_grow (%u bytes)\n",
258 for (i
= blkmap
->nents
; i
> idx
; i
--)
259 blkmap
->ents
[i
] = blkmap
->ents
[i
- 1];
260 blkmap
->ents
[idx
] = newent
;
265 * Return the last offset in a block map.
275 ent
= blkmap
->ents
[blkmap
->nents
- 1];
276 return ent
->startoff
+ ent
->nblks
;
280 * Return the next offset in a block map.
293 if (o
== NULLDFILOFF
) {
295 ent
= blkmap
->ents
[0];
296 return ent
->startoff
;
298 entp
= &blkmap
->ents
[*t
];
300 if (o
< ent
->startoff
+ ent
->nblks
- 1)
303 if (entp
>= &blkmap
->ents
[blkmap
->nents
])
307 return ent
->startoff
;
311 * Set a block value in a block map.
325 for (entp
= blkmap
->ents
; entp
< &blkmap
->ents
[blkmap
->nents
]; entp
++) {
327 if (o
< ent
->startoff
- 1) {
328 ent
= blkent_new(o
, b
, 1);
329 blkmap_grow(blkmapp
, entp
, ent
);
332 if (o
== ent
->startoff
- 1) {
333 blkent_prepend(entp
, b
, 1);
336 if (o
>= ent
->startoff
&& o
< ent
->startoff
+ ent
->nblks
) {
337 ent
->blks
[o
- ent
->startoff
] = b
;
340 if (o
> ent
->startoff
+ ent
->nblks
)
342 blkent_append(entp
, b
, 1);
343 if (entp
== &blkmap
->ents
[blkmap
->nents
- 1])
347 if (ent
->startoff
+ ent
->nblks
< nextent
->startoff
)
349 blkent_append(entp
, nextent
->blks
[0], nextent
->nblks
);
350 blkmap_shrink(blkmap
, &entp
[1]);
353 ent
= blkent_new(o
, b
, 1);
354 blkmap_grow(blkmapp
, entp
, ent
);
358 * Set an extent into a block map.
373 if (!blkmap
->nents
) {
374 blkmap
->ents
[0] = blkent_new(o
, b
, c
);
378 entp
= &blkmap
->ents
[blkmap
->nents
- 1];
380 if (ent
->startoff
+ ent
->nblks
== o
) {
381 blkent_append(entp
, b
, c
);
384 if (ent
->startoff
+ ent
->nblks
< o
) {
385 ent
= blkent_new(o
, b
, c
);
386 blkmap_grow(blkmapp
, &blkmap
->ents
[blkmap
->nents
], ent
);
389 for (i
= 0; i
< c
; i
++)
390 blkmap_set_blk(blkmapp
, o
+ i
, b
+ i
);
394 * Make a block map smaller.
405 idx
= (int)(entp
- blkmap
->ents
);
406 for (i
= idx
+ 1; i
< blkmap
->nents
; i
++)
407 blkmap
->ents
[i
] = blkmap
->ents
[i
- 1];