]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - repair/bmap.c
2 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "err_protos.h"
24 * Block mapping code taken from xfs_db.
28 * Append an extent to the block entry.
41 size
= BLKENT_SIZE(c
+ ent
->nblks
);
42 if ((*entp
= ent
= realloc(ent
, size
)) == NULL
) {
43 do_warn(_("realloc failed in blkent_append (%u bytes)\n"),
47 for (i
= 0; i
< c
; i
++)
48 ent
->blks
[ent
->nblks
+ i
] = b
+ i
;
53 * Make a new block entry.
64 if ((ent
= malloc(BLKENT_SIZE(c
))) == NULL
) {
65 do_warn(_("malloc failed in blkent_new (%u bytes)\n"),
71 for (i
= 0; i
< c
; i
++)
77 * Prepend an extent to the block entry.
90 if ((newent
= malloc(BLKENT_SIZE(oldent
->nblks
+ c
))) == NULL
) {
91 do_warn(_("malloc failed in blkent_prepend (%u bytes)\n"),
92 BLKENT_SIZE(oldent
->nblks
+ c
));
96 newent
->nblks
= oldent
->nblks
+ c
;
97 newent
->startoff
= oldent
->startoff
- c
;
98 for (i
= 0; i
< c
; i
++)
99 newent
->blks
[i
] = b
+ c
;
100 for (; i
< oldent
->nblks
+ c
; i
++)
101 newent
->blks
[i
] = oldent
->blks
[i
- c
];
107 * Allocate a block map.
117 if ((blkmap
= malloc(BLKMAP_SIZE(nex
))) == NULL
) {
118 do_warn(_("malloc failed in blkmap_alloc (%u bytes)\n"),
122 blkmap
->naents
= nex
;
139 for (i
= 0, entp
= blkmap
->ents
; i
< blkmap
->nents
; i
++, entp
++)
145 * Get one entry from a block map.
156 for (i
= 0, entp
= blkmap
->ents
; i
< blkmap
->nents
; i
++, entp
++) {
158 if (o
>= ent
->startoff
&& o
< ent
->startoff
+ ent
->nblks
)
159 return ent
->blks
[o
- ent
->startoff
];
165 * Get a chunk of entries from a block map.
173 bmap_ext_t
*bmpp_single
)
184 * in the common case, when mp->m_dirblkfsbs == 1,
185 * avoid additional malloc/free overhead
187 bmpp_single
->startblock
= blkmap_get(blkmap
, o
);
188 bmpp_single
->blockcount
= 1;
189 bmpp_single
->startoff
= 0;
190 bmpp_single
->flag
= 0;
192 return (bmpp_single
->startblock
!= NULLDFSBNO
) ? 1 : 0;
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(_("blkmap_getn realloc failed"
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];