]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blame - e2fsck/pass1b.c
e2fsck: remove get_filename_hash() prototype
[thirdparty/e2fsprogs.git] / e2fsck / pass1b.c
CommitLineData
3839e657
TT
1/*
2 * pass1b.c --- Pass #1b of e2fsck
3 *
4 * This file contains pass1B, pass1C, and pass1D of e2fsck. They are
5 * only invoked if pass 1 discovered blocks which are in use by more
6 * than one inode.
efc6f628 7 *
3839e657
TT
8 * Pass1B scans the data blocks of all the inodes again, generating a
9 * complete list of duplicate blocks and which inodes have claimed
10 * them.
11 *
12 * Pass1C does a tree-traversal of the filesystem, to determine the
13 * parent directories of these inodes. This step is necessary so that
14 * e2fsck can print out the pathnames of affected inodes.
15 *
16 * Pass1D is a reconciliation pass. For each inode with duplicate
17 * blocks, the user is prompted if s/he would like to clone the file
18 * (so that the file gets a fresh copy of the duplicated blocks) or
19 * simply to delete the file.
efc6f628 20 *
21c84b71
TT
21 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
22 *
23 * %Begin-Header%
24 * This file may be redistributed under the terms of the GNU Public
25 * License.
26 * %End-Header%
efc6f628 27 *
3839e657
TT
28 */
29
d1154eb4 30#include "config.h"
3839e657 31#include <time.h>
50e1e10f
TT
32#ifdef HAVE_ERRNO_H
33#include <errno.h>
34#endif
3839e657 35
0c193f82
TT
36#ifdef HAVE_INTTYPES_H
37#include <inttypes.h>
38#endif
39
d2ee56d8 40#ifndef HAVE_INTPTR_T
9c07dc00 41typedef long intptr_t;
d2ee56d8
TT
42#endif
43
0c193f82
TT
44/* Needed for architectures where sizeof(int) != sizeof(void *) */
45#define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val))
46#define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr))
47
3839e657
TT
48#include <et/com_err.h>
49#include "e2fsck.h"
50
21c84b71 51#include "problem.h"
3dca12fb 52#include "support/dict.h"
21c84b71 53
342d847d
TT
54/* Define an extension to the ext2 library's block count information */
55#define BLOCK_COUNT_EXTATTR (-5)
56
f51b4d33
TT
57struct cluster_el {
58 blk64_t cluster;
59 struct cluster_el *next;
838e773e
TT
60};
61
62struct inode_el {
63 ext2_ino_t inode;
64 struct inode_el *next;
65};
66
f51b4d33 67struct dup_cluster {
3839e657 68 int num_bad;
838e773e 69 struct inode_el *inode_list;
3839e657
TT
70};
71
72/*
73 * This structure stores information about a particular inode which
74 * is sharing blocks with other inodes. This information is collected
75 * to display to the user, so that the user knows what files he or she
76 * is dealing with, when trying to decide how to resolve the conflict
77 * of multiply-claimed blocks.
78 */
79struct dup_inode {
838e773e 80 ext2_ino_t dir;
21c84b71 81 int num_dupblocks;
bc1ec4b4 82 struct ext2_inode_large inode;
f51b4d33 83 struct cluster_el *cluster_list;
3839e657
TT
84};
85
a63745e8
VAH
86static int process_pass1b_block(ext2_filsys fs, blk64_t *blocknr,
87 e2_blkcnt_t blockcnt, blk64_t ref_blk,
133a56dc 88 int ref_offset, void *priv_data);
838e773e
TT
89static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
90 struct dup_inode *dp, char *block_buf);
974d57d3
TT
91static errcode_t clone_file(e2fsck_t ctx, ext2_ino_t ino,
92 struct dup_inode *dp, char* block_buf);
f51b4d33
TT
93static int check_if_fs_block(e2fsck_t ctx, blk64_t test_block);
94static int check_if_fs_cluster(e2fsck_t ctx, blk64_t cluster);
80c5d7e4 95
1b6bf175
TT
96static void pass1b(e2fsck_t ctx, char *block_buf);
97static void pass1c(e2fsck_t ctx, char *block_buf);
98static void pass1d(e2fsck_t ctx, char *block_buf);
3839e657 99
3839e657 100static int dup_inode_count = 0;
81cae650 101static int dup_inode_founddir = 0;
3839e657 102
f51b4d33 103static dict_t clstr_dict, ino_dict;
838e773e 104
f3db3566 105static ext2fs_inode_bitmap inode_dup_map;
3839e657 106
838e773e
TT
107static int dict_int_cmp(const void *a, const void *b)
108{
0c193f82 109 intptr_t ia, ib;
838e773e 110
0c193f82
TT
111 ia = (intptr_t)a;
112 ib = (intptr_t)b;
838e773e
TT
113
114 return (ia-ib);
115}
116
117/*
118 * Add a duplicate block record
119 */
f51b4d33 120static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk64_t cluster,
bc1ec4b4 121 struct ext2_inode_large *inode)
838e773e
TT
122{
123 dnode_t *n;
f51b4d33 124 struct dup_cluster *db;
838e773e 125 struct dup_inode *di;
f51b4d33 126 struct cluster_el *cluster_el;
838e773e
TT
127 struct inode_el *ino_el;
128
f51b4d33 129 n = dict_lookup(&clstr_dict, INT_TO_VOIDPTR(cluster));
838e773e 130 if (n)
f51b4d33 131 db = (struct dup_cluster *) dnode_get(n);
838e773e 132 else {
f51b4d33
TT
133 db = (struct dup_cluster *) e2fsck_allocate_memory(ctx,
134 sizeof(struct dup_cluster), "duplicate cluster header");
838e773e
TT
135 db->num_bad = 0;
136 db->inode_list = 0;
f51b4d33 137 dict_alloc_insert(&clstr_dict, INT_TO_VOIDPTR(cluster), db);
838e773e
TT
138 }
139 ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
140 sizeof(struct inode_el), "inode element");
141 ino_el->inode = ino;
142 ino_el->next = db->inode_list;
143 db->inode_list = ino_el;
144 db->num_bad++;
145
0c193f82 146 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
838e773e
TT
147 if (n)
148 di = (struct dup_inode *) dnode_get(n);
149 else {
150 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
151 sizeof(struct dup_inode), "duplicate inode header");
81cae650
JG
152 if (ino == EXT2_ROOT_INO) {
153 di->dir = EXT2_ROOT_INO;
154 dup_inode_founddir++;
155 } else
156 di->dir = 0;
157
838e773e 158 di->num_dupblocks = 0;
f51b4d33 159 di->cluster_list = 0;
838e773e 160 di->inode = *inode;
0c193f82 161 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
838e773e 162 }
f51b4d33
TT
163 cluster_el = (struct cluster_el *) e2fsck_allocate_memory(ctx,
164 sizeof(struct cluster_el), "cluster element");
165 cluster_el->cluster = cluster;
166 cluster_el->next = di->cluster_list;
167 di->cluster_list = cluster_el;
838e773e
TT
168 di->num_dupblocks++;
169}
170
171/*
172 * Free a duplicate inode record
173 */
efc6f628 174static void inode_dnode_free(dnode_t *node,
54434927 175 void *context EXT2FS_ATTR((unused)))
838e773e
TT
176{
177 struct dup_inode *di;
f51b4d33 178 struct cluster_el *p, *next;
838e773e
TT
179
180 di = (struct dup_inode *) dnode_get(node);
f51b4d33 181 for (p = di->cluster_list; p; p = next) {
838e773e
TT
182 next = p->next;
183 free(p);
184 }
23f75f6e 185 free(di);
838e773e
TT
186 free(node);
187}
188
189/*
f51b4d33 190 * Free a duplicate cluster record
838e773e 191 */
f51b4d33
TT
192static void cluster_dnode_free(dnode_t *node,
193 void *context EXT2FS_ATTR((unused)))
838e773e 194{
f51b4d33 195 struct dup_cluster *dc;
838e773e
TT
196 struct inode_el *p, *next;
197
f51b4d33
TT
198 dc = (struct dup_cluster *) dnode_get(node);
199 for (p = dc->inode_list; p; p = next) {
838e773e
TT
200 next = p->next;
201 free(p);
202 }
f51b4d33 203 free(dc);
838e773e
TT
204 free(node);
205}
206
207
3839e657
TT
208/*
209 * Main procedure for handling duplicate blocks
210 */
08b21301 211void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
3839e657 212{
1b6bf175 213 ext2_filsys fs = ctx->fs;
1b6bf175 214 struct problem_context pctx;
fea390e2
KC
215#ifdef RESOURCE_TRACK
216 struct resource_track rtrack;
217#endif
1b6bf175
TT
218
219 clear_problem_context(&pctx);
efc6f628 220
830b44f4
TT
221 pctx.errcode = e2fsck_allocate_inode_bitmap(fs,
222 _("multiply claimed inode map"),
223 EXT2FS_BMAP64_RBTREE, "inode_dup_map",
224 &inode_dup_map);
1b6bf175
TT
225 if (pctx.errcode) {
226 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
f8188fff
TT
227 ctx->flags |= E2F_FLAG_ABORT;
228 return;
3839e657 229 }
838e773e
TT
230
231 dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
f51b4d33 232 dict_init(&clstr_dict, DICTCOUNT_T_MAX, dict_int_cmp);
838e773e 233 dict_set_allocator(&ino_dict, NULL, inode_dnode_free, NULL);
f51b4d33 234 dict_set_allocator(&clstr_dict, NULL, cluster_dnode_free, NULL);
efc6f628 235
fea390e2 236 init_resource_track(&rtrack, ctx->fs->io);
1b6bf175 237 pass1b(ctx, block_buf);
9facd076 238 print_resource_track(ctx, "Pass 1b", &rtrack, ctx->fs->io);
fea390e2 239
fea390e2 240 init_resource_track(&rtrack, ctx->fs->io);
1b6bf175 241 pass1c(ctx, block_buf);
9facd076 242 print_resource_track(ctx, "Pass 1c", &rtrack, ctx->fs->io);
fea390e2 243
fea390e2 244 init_resource_track(&rtrack, ctx->fs->io);
1b6bf175 245 pass1d(ctx, block_buf);
9facd076 246 print_resource_track(ctx, "Pass 1d", &rtrack, ctx->fs->io);
fea390e2 247
3839e657
TT
248 /*
249 * Time to free all of the accumulated data structures that we
250 * don't need anymore.
251 */
838e773e 252 dict_free_nodes(&ino_dict);
f51b4d33 253 dict_free_nodes(&clstr_dict);
23f75f6e 254 ext2fs_free_inode_bitmap(inode_dup_map);
3839e657
TT
255}
256
257/*
258 * Scan the inodes looking for inodes that contain duplicate blocks.
259 */
260struct process_block_struct {
838e773e 261 e2fsck_t ctx;
86c627ec
TT
262 ext2_ino_t ino;
263 int dup_blocks;
9a1d614d 264 blk64_t cur_cluster, phys_cluster;
28b966d7 265 blk64_t last_blk;
bc1ec4b4 266 struct ext2_inode_large *inode;
1b6bf175 267 struct problem_context *pctx;
3839e657
TT
268};
269
08b21301 270static void pass1b(e2fsck_t ctx, char *block_buf)
3839e657 271{
1b6bf175 272 ext2_filsys fs = ctx->fs;
24c91184 273 ext2_ino_t ino = 0;
bc1ec4b4 274 struct ext2_inode_large inode;
3839e657 275 ext2_inode_scan scan;
3839e657 276 struct process_block_struct pb;
1b6bf175 277 struct problem_context pctx;
28b966d7 278 problem_t op;
efc6f628 279
1b6bf175 280 clear_problem_context(&pctx);
efc6f628 281
151786fc
TT
282 if (!(ctx->options & E2F_OPT_PREEN))
283 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
1b6bf175
TT
284 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
285 &scan);
286 if (pctx.errcode) {
287 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
f8188fff
TT
288 ctx->flags |= E2F_FLAG_ABORT;
289 return;
3839e657 290 }
bc1ec4b4 291 ctx->stashed_inode = EXT2_INODE(&inode);
1b6bf175
TT
292 pb.ctx = ctx;
293 pb.pctx = &pctx;
133a56dc 294 pctx.str = "pass1b";
d237a78e 295 while (1) {
0f5eba75
AD
296 if (ino % (fs->super->s_inodes_per_group * 4) == 1) {
297 if (e2fsck_mmp_update(fs))
298 fatal_error(ctx, 0);
299 }
bc1ec4b4
TT
300 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
301 EXT2_INODE(&inode), sizeof(inode));
d237a78e
TT
302 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
303 continue;
304 if (pctx.errcode) {
88e172a9 305 pctx.ino = ino;
d237a78e
TT
306 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
307 ctx->flags |= E2F_FLAG_ABORT;
308 return;
309 }
310 if (!ino)
311 break;
1b6bf175 312 pctx.ino = ctx->stashed_ino = ino;
3839e657 313 if ((ino != EXT2_BAD_INO) &&
c5d2f50d 314 !ext2fs_test_inode_bitmap2(ctx->inode_used_map, ino))
d237a78e 315 continue;
3839e657
TT
316
317 pb.ino = ino;
318 pb.dup_blocks = 0;
838e773e 319 pb.inode = &inode;
b23f2f4d 320 pb.cur_cluster = ~0;
9a1d614d 321 pb.phys_cluster = ~0;
28b966d7
DW
322 pb.last_blk = 0;
323 pb.pctx->blk = pb.pctx->blk2 = 0;
0684a4f3 324
bc1ec4b4 325 if (ext2fs_inode_has_valid_blocks2(fs, EXT2_INODE(&inode)) ||
0684a4f3 326 (ino == EXT2_BAD_INO))
a63745e8 327 pctx.errcode = ext2fs_block_iterate3(fs, ino,
15d482ba
TT
328 BLOCK_FLAG_READ_ONLY, block_buf,
329 process_pass1b_block, &pb);
7501ce3e 330 /* If the feature is not set, attrs will be cleared later anyway */
86f3b6cf 331 if (ext2fs_has_feature_xattr(fs->super) &&
bc1ec4b4
TT
332 ext2fs_file_acl_block(fs, EXT2_INODE(&inode))) {
333 blk64_t blk = ext2fs_file_acl_block(fs, EXT2_INODE(&inode));
a63745e8 334 process_pass1b_block(fs, &blk,
342d847d 335 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
bc1ec4b4 336 ext2fs_file_acl_block_set(fs, EXT2_INODE(&inode), blk);
7501ce3e 337 }
3839e657 338 if (pb.dup_blocks) {
28b966d7
DW
339 if (ino != EXT2_BAD_INO) {
340 op = pctx.blk == pctx.blk2 ?
341 PR_1B_DUP_BLOCK : PR_1B_DUP_RANGE;
342 fix_problem(ctx, op, pb.pctx);
343 }
1b6bf175 344 end_problem_latch(ctx, PR_LATCH_DBLOCK);
838e773e
TT
345 if (ino >= EXT2_FIRST_INODE(fs->super) ||
346 ino == EXT2_ROOT_INO)
3839e657
TT
347 dup_inode_count++;
348 }
133a56dc
TT
349 if (pctx.errcode)
350 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
3839e657
TT
351 }
352 ext2fs_close_inode_scan(scan);
71d521c6 353 e2fsck_use_inode_shortcuts(ctx, 0);
3839e657
TT
354}
355
54434927 356static int process_pass1b_block(ext2_filsys fs EXT2FS_ATTR((unused)),
a63745e8 357 blk64_t *block_nr,
b23f2f4d 358 e2_blkcnt_t blockcnt,
a63745e8 359 blk64_t ref_blk EXT2FS_ATTR((unused)),
54434927 360 int ref_offset EXT2FS_ATTR((unused)),
53ef44c4 361 void *priv_data)
3839e657
TT
362{
363 struct process_block_struct *p;
1b6bf175 364 e2fsck_t ctx;
9a1d614d 365 blk64_t lc, pc;
28b966d7 366 problem_t op;
3839e657 367
4a05268c 368 if (*block_nr == 0)
3839e657 369 return 0;
54dc7ca2 370 p = (struct process_block_struct *) priv_data;
1b6bf175 371 ctx = p->ctx;
b23f2f4d 372 lc = EXT2FS_B2C(fs, blockcnt);
9a1d614d 373 pc = EXT2FS_B2C(fs, *block_nr);
efc6f628 374
c5d2f50d 375 if (!ext2fs_test_block_bitmap2(ctx->block_dup_map, *block_nr))
b23f2f4d 376 goto finish;
efc6f628 377
838e773e
TT
378 /* OK, this is a duplicate block */
379 if (p->ino != EXT2_BAD_INO) {
28b966d7
DW
380 if (p->last_blk + 1 != *block_nr) {
381 if (p->last_blk) {
382 op = p->pctx->blk == p->pctx->blk2 ?
383 PR_1B_DUP_BLOCK :
384 PR_1B_DUP_RANGE;
385 fix_problem(ctx, op, p->pctx);
386 }
387 p->pctx->blk = *block_nr;
388 }
389 p->pctx->blk2 = *block_nr;
390 p->last_blk = *block_nr;
3839e657 391 }
838e773e 392 p->dup_blocks++;
c5d2f50d 393 ext2fs_mark_inode_bitmap2(inode_dup_map, p->ino);
838e773e 394
9a1d614d
DW
395 /*
396 * Qualifications for submitting a block for duplicate processing:
397 * It's an extent/indirect block (and has a negative logical offset);
398 * we've crossed a logical cluster boundary; or the physical cluster
399 * suddenly changed, which indicates that blocks in a logical cluster
400 * are mapped to multiple physical clusters.
401 */
402 if (blockcnt < 0 || lc != p->cur_cluster || pc != p->phys_cluster)
b23f2f4d 403 add_dupe(ctx, p->ino, EXT2FS_B2C(fs, *block_nr), p->inode);
efc6f628 404
b23f2f4d
TT
405finish:
406 p->cur_cluster = lc;
9a1d614d 407 p->phys_cluster = pc;
3839e657
TT
408 return 0;
409}
410
3839e657
TT
411/*
412 * Pass 1c: Scan directories for inodes with duplicate blocks. This
413 * is used so that we can print pathnames when prompting the user for
414 * what to do.
415 */
21c84b71 416struct search_dir_struct {
3839e657 417 int count;
86c627ec
TT
418 ext2_ino_t first_inode;
419 ext2_ino_t max_inode;
3839e657
TT
420};
421
86c627ec 422static int search_dirent_proc(ext2_ino_t dir, int entry,
21c84b71 423 struct ext2_dir_entry *dirent,
efc6f628 424 int offset EXT2FS_ATTR((unused)),
54434927 425 int blocksize EXT2FS_ATTR((unused)),
efc6f628 426 char *buf EXT2FS_ATTR((unused)),
54434927 427 void *priv_data)
21c84b71 428{
54dc7ca2 429 struct search_dir_struct *sd;
21c84b71 430 struct dup_inode *p;
838e773e 431 dnode_t *n;
54dc7ca2
TT
432
433 sd = (struct search_dir_struct *) priv_data;
434
521e3685
TT
435 if (dirent->inode > sd->max_inode)
436 /* Should abort this inode, but not everything */
efc6f628 437 return 0;
521e3685 438
838e773e 439 if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
c5d2f50d 440 !ext2fs_test_inode_bitmap2(inode_dup_map, dirent->inode))
21c84b71
TT
441 return 0;
442
0c193f82 443 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
838e773e 444 if (!n)
21c84b71 445 return 0;
838e773e 446 p = (struct dup_inode *) dnode_get(n);
3d51ff87
JG
447 if (!p->dir) {
448 p->dir = dir;
449 sd->count--;
450 }
21c84b71
TT
451
452 return(sd->count ? 0 : DIRENT_ABORT);
453}
454
455
08b21301 456static void pass1c(e2fsck_t ctx, char *block_buf)
3839e657 457{
1b6bf175 458 ext2_filsys fs = ctx->fs;
21c84b71 459 struct search_dir_struct sd;
1b6bf175
TT
460 struct problem_context pctx;
461
462 clear_problem_context(&pctx);
3839e657 463
151786fc
TT
464 if (!(ctx->options & E2F_OPT_PREEN))
465 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
3839e657 466
3839e657
TT
467 /*
468 * Search through all directories to translate inodes to names
469 * (by searching for the containing directory for that inode.)
470 */
81cae650 471 sd.count = dup_inode_count - dup_inode_founddir;
21c84b71 472 sd.first_inode = EXT2_FIRST_INODE(fs->super);
521e3685 473 sd.max_inode = fs->super->s_inodes_count;
21c84b71
TT
474 ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
475 search_dirent_proc, &sd);
efc6f628 476}
3839e657 477
1b6bf175 478static void pass1d(e2fsck_t ctx, char *block_buf)
3839e657 479{
1b6bf175 480 ext2_filsys fs = ctx->fs;
838e773e 481 struct dup_inode *p, *t;
f51b4d33 482 struct dup_cluster *q;
838e773e 483 ext2_ino_t *shared, ino;
3839e657
TT
484 int shared_len;
485 int i;
3839e657 486 int file_ok;
521e3685 487 int meta_data = 0;
21c84b71 488 struct problem_context pctx;
838e773e 489 dnode_t *n, *m;
f51b4d33 490 struct cluster_el *s;
838e773e 491 struct inode_el *r;
efc6f628 492
1b6bf175 493 clear_problem_context(&pctx);
efc6f628 494
151786fc
TT
495 if (!(ctx->options & E2F_OPT_PREEN))
496 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
f8188fff 497 e2fsck_read_bitmaps(ctx);
3839e657 498
838e773e 499 pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
1b6bf175 500 fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
86c627ec 501 shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
838e773e 502 sizeof(ext2_ino_t) * dict_count(&ino_dict),
54dc7ca2 503 "Shared inode list");
838e773e
TT
504 for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
505 p = (struct dup_inode *) dnode_get(n);
3839e657
TT
506 shared_len = 0;
507 file_ok = 1;
0c193f82 508 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
5e916143 509 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
3839e657
TT
510 continue;
511
512 /*
838e773e
TT
513 * Find all of the inodes which share blocks with this
514 * one. First we find all of the duplicate blocks
515 * belonging to this inode, and then search each block
516 * get the list of inodes, and merge them together.
3839e657 517 */
f51b4d33
TT
518 for (s = p->cluster_list; s; s = s->next) {
519 m = dict_lookup(&clstr_dict,
520 INT_TO_VOIDPTR(s->cluster));
838e773e
TT
521 if (!m)
522 continue; /* Should never happen... */
f51b4d33 523 q = (struct dup_cluster *) dnode_get(m);
3839e657
TT
524 if (q->num_bad > 1)
525 file_ok = 0;
f51b4d33 526 if (check_if_fs_cluster(ctx, s->cluster)) {
521e3685
TT
527 file_ok = 0;
528 meta_data = 1;
529 }
efc6f628 530
3839e657
TT
531 /*
532 * Add all inodes used by this block to the
533 * shared[] --- which is a unique list, so
534 * if an inode is already in shared[], don't
535 * add it again.
536 */
838e773e
TT
537 for (r = q->inode_list; r; r = r->next) {
538 if (r->inode == ino)
3839e657
TT
539 continue;
540 for (i = 0; i < shared_len; i++)
838e773e 541 if (shared[i] == r->inode)
3839e657
TT
542 break;
543 if (i == shared_len) {
838e773e 544 shared[shared_len++] = r->inode;
3839e657
TT
545 }
546 }
547 }
21c84b71
TT
548
549 /*
550 * Report the inode that we are working on
551 */
bc1ec4b4 552 pctx.inode = EXT2_INODE(&p->inode);
838e773e 553 pctx.ino = ino;
21c84b71
TT
554 pctx.dir = p->dir;
555 pctx.blkcount = p->num_dupblocks;
521e3685 556 pctx.num = meta_data ? shared_len+1 : shared_len;
1b6bf175 557 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
21c84b71
TT
558 pctx.blkcount = 0;
559 pctx.num = 0;
efc6f628 560
521e3685 561 if (meta_data)
1b6bf175 562 fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
efc6f628 563
3839e657 564 for (i = 0; i < shared_len; i++) {
0c193f82 565 m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
838e773e
TT
566 if (!m)
567 continue; /* should never happen */
568 t = (struct dup_inode *) dnode_get(m);
21c84b71
TT
569 /*
570 * Report the inode that we are sharing with
571 */
bc1ec4b4 572 pctx.inode = EXT2_INODE(&t->inode);
838e773e
TT
573 pctx.ino = shared[i];
574 pctx.dir = t->dir;
1b6bf175 575 fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
3839e657 576 }
9a1d614d
DW
577 /*
578 * Even if the file shares blocks with itself, we still need to
579 * clone the blocks.
580 */
581 if (file_ok && (meta_data ? shared_len+1 : shared_len) != 0) {
1b6bf175 582 fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
3839e657
TT
583 continue;
584 }
1b6bf175 585 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
838e773e 586 pctx.errcode = clone_file(ctx, ino, p, block_buf);
1b6bf175
TT
587 if (pctx.errcode)
588 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
589 else
3839e657 590 continue;
3839e657 591 }
1b6bf175 592 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
838e773e 593 delete_file(ctx, ino, p, block_buf);
3839e657
TT
594 else
595 ext2fs_unmark_valid(fs);
3839e657 596 }
c4e3d3f3 597 ext2fs_free_mem(&shared);
3839e657
TT
598}
599
7abb2bdc
TT
600/*
601 * Drop the refcount on the dup_block structure, and clear the entry
602 * in the block_dup_map if appropriate.
603 */
f51b4d33
TT
604static void decrement_badcount(e2fsck_t ctx, blk64_t block,
605 struct dup_cluster *p)
7abb2bdc
TT
606{
607 p->num_bad--;
608 if (p->num_bad <= 0 ||
f51b4d33
TT
609 (p->num_bad == 1 && !check_if_fs_block(ctx, block))) {
610 if (check_if_fs_cluster(ctx, EXT2FS_B2C(ctx->fs, block)))
611 return;
c5d2f50d 612 ext2fs_unmark_block_bitmap2(ctx->block_dup_map, block);
f51b4d33 613 }
7abb2bdc
TT
614}
615
3839e657 616static int delete_file_block(ext2_filsys fs,
a63745e8 617 blk64_t *block_nr,
b23f2f4d 618 e2_blkcnt_t blockcnt,
a63745e8 619 blk64_t ref_block EXT2FS_ATTR((unused)),
54434927 620 int ref_offset EXT2FS_ATTR((unused)),
54dc7ca2 621 void *priv_data)
3839e657 622{
54dc7ca2 623 struct process_block_struct *pb;
f51b4d33 624 struct dup_cluster *p;
838e773e 625 dnode_t *n;
1b6bf175 626 e2fsck_t ctx;
b23f2f4d 627 blk64_t c, lc;
1b6bf175 628
54dc7ca2 629 pb = (struct process_block_struct *) priv_data;
1b6bf175 630 ctx = pb->ctx;
3839e657 631
4a05268c 632 if (*block_nr == 0)
3839e657
TT
633 return 0;
634
f51b4d33 635 c = EXT2FS_B2C(fs, *block_nr);
b23f2f4d 636 lc = EXT2FS_B2C(fs, blockcnt);
c5d2f50d 637 if (ext2fs_test_block_bitmap2(ctx->block_dup_map, *block_nr)) {
f51b4d33 638 n = dict_lookup(&clstr_dict, INT_TO_VOIDPTR(c));
838e773e 639 if (n) {
b0f5fa88
EW
640 if (lc != pb->cur_cluster) {
641 p = (struct dup_cluster *) dnode_get(n);
b23f2f4d 642 decrement_badcount(ctx, *block_nr, p);
b0f5fa88
EW
643 pb->dup_blocks++;
644 }
3839e657
TT
645 } else
646 com_err("delete_file_block", 0,
a63745e8 647 _("internal error: can't find dup_blk for %llu\n"),
3839e657
TT
648 *block_nr);
649 } else {
8dd650ab
DW
650 if ((*block_nr % EXT2FS_CLUSTER_RATIO(ctx->fs)) == 0)
651 ext2fs_block_alloc_stats2(fs, *block_nr, -1);
624e4a64 652 pb->dup_blocks++;
3839e657 653 }
b23f2f4d 654 pb->cur_cluster = lc;
efc6f628 655
3839e657
TT
656 return 0;
657}
efc6f628 658
838e773e
TT
659static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
660 struct dup_inode *dp, char* block_buf)
3839e657 661{
1b6bf175 662 ext2_filsys fs = ctx->fs;
3839e657 663 struct process_block_struct pb;
133a56dc 664 struct problem_context pctx;
0684a4f3 665 unsigned int count;
3839e657 666
133a56dc 667 clear_problem_context(&pctx);
838e773e 668 pctx.ino = pb.ino = ino;
624e4a64 669 pb.dup_blocks = 0;
1b6bf175 670 pb.ctx = ctx;
133a56dc 671 pctx.str = "delete_file";
b23f2f4d 672 pb.cur_cluster = ~0;
133a56dc 673
bc1ec4b4 674 if (ext2fs_inode_has_valid_blocks2(fs, EXT2_INODE(&dp->inode)))
68477355
TT
675 pctx.errcode = ext2fs_block_iterate3(fs, ino,
676 BLOCK_FLAG_READ_ONLY,
677 block_buf,
678 delete_file_block, &pb);
133a56dc
TT
679 if (pctx.errcode)
680 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
1b6bf175 681 if (ctx->inode_bad_map)
c5d2f50d 682 ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino);
68477355
TT
683 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(dp->inode.i_mode));
684 quota_data_sub(ctx->qctx, &dp->inode, ino,
685 pb.dup_blocks * fs->blocksize);
686 quota_data_inodes(ctx->qctx, &dp->inode, ino, -1);
0684a4f3
TT
687
688 /* Inode may have changed by block_iterate, so reread it */
bc1ec4b4
TT
689 e2fsck_read_inode_full(ctx, ino, EXT2_INODE(&dp->inode),
690 sizeof(dp->inode), "delete_file");
691 e2fsck_clear_inode(ctx, ino, EXT2_INODE(&dp->inode), 0, "delete_file");
692 if (ext2fs_file_acl_block(fs, EXT2_INODE(&dp->inode)) &&
86f3b6cf 693 ext2fs_has_feature_xattr(fs->super)) {
bc1ec4b4
TT
694 blk64_t file_acl_block = ext2fs_file_acl_block(fs,
695 EXT2_INODE(&dp->inode));
696
0684a4f3 697 count = 1;
bc1ec4b4 698 pctx.errcode = ext2fs_adjust_ea_refcount3(fs, file_acl_block,
39f5659a 699 block_buf, -1, &count, ino);
0684a4f3
TT
700 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
701 pctx.errcode = 0;
702 count = 1;
703 }
704 if (pctx.errcode) {
bc1ec4b4 705 pctx.blk = file_acl_block;
0684a4f3
TT
706 fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
707 }
708 /*
709 * If the count is zero, then arrange to have the
710 * block deleted. If the block is in the block_dup_map,
711 * also call delete_file_block since it will take care
712 * of keeping the accounting straight.
713 */
714 if ((count == 0) ||
c5d2f50d 715 ext2fs_test_block_bitmap2(ctx->block_dup_map,
bc1ec4b4
TT
716 file_acl_block)) {
717 delete_file_block(fs, &file_acl_block,
0684a4f3 718 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
bc1ec4b4
TT
719 ext2fs_file_acl_block_set(fs, EXT2_INODE(&dp->inode),
720 file_acl_block);
721 quota_data_sub(ctx->qctx, &dp->inode, ino,
722 fs->blocksize);
a63745e8 723 }
0684a4f3 724 }
3839e657
TT
725}
726
727struct clone_struct {
728 errcode_t errcode;
f51b4d33
TT
729 blk64_t dup_cluster;
730 blk64_t alloc_block;
9a1d614d 731 ext2_ino_t dir, ino;
3839e657 732 char *buf;
1b6bf175 733 e2fsck_t ctx;
bc1ec4b4 734 struct ext2_inode_large *inode;
09282b8a
DW
735
736 struct dup_cluster *save_dup_cluster;
737 blk64_t save_blocknr;
3839e657
TT
738};
739
09282b8a
DW
740/*
741 * Decrement the bad count *after* we've shown that (a) we can allocate a
742 * replacement block and (b) remap the file blocks. Unfortunately, there's no
743 * way to find out if the remap succeeded until either the next
744 * clone_file_block() call (an error when remapping the block after returning
745 * BLOCK_CHANGED will halt the iteration) or after block_iterate() returns.
746 * Otherwise, it's possible that we decrease the badcount once in preparation
747 * to remap, then the remap fails (either we can't find a replacement block or
748 * we have to split the extent tree and can't find a new extent block), so we
749 * delete the file, which decreases the badcount again.
750 */
751static void deferred_dec_badcount(struct clone_struct *cs)
752{
753 if (!cs->save_dup_cluster)
754 return;
755 decrement_badcount(cs->ctx, cs->save_blocknr, cs->save_dup_cluster);
756 cs->save_dup_cluster = NULL;
757}
758
3839e657 759static int clone_file_block(ext2_filsys fs,
a63745e8 760 blk64_t *block_nr,
133a56dc 761 e2_blkcnt_t blockcnt,
a63745e8 762 blk64_t ref_block EXT2FS_ATTR((unused)),
54434927 763 int ref_offset EXT2FS_ATTR((unused)),
54dc7ca2 764 void *priv_data)
3839e657 765{
09282b8a 766 struct dup_cluster *p = NULL;
c5d2f50d 767 blk64_t new_block;
3839e657 768 errcode_t retval;
54dc7ca2 769 struct clone_struct *cs = (struct clone_struct *) priv_data;
838e773e 770 dnode_t *n;
1b6bf175 771 e2fsck_t ctx;
f51b4d33
TT
772 blk64_t c;
773 int is_meta = 0;
3839e657 774
1b6bf175 775 ctx = cs->ctx;
09282b8a 776 deferred_dec_badcount(cs);
efc6f628 777
4a05268c 778 if (*block_nr == 0)
3839e657
TT
779 return 0;
780
f51b4d33
TT
781 c = EXT2FS_B2C(fs, blockcnt);
782 if (check_if_fs_cluster(ctx, EXT2FS_B2C(fs, *block_nr)))
783 is_meta = 1;
784
b23f2f4d
TT
785 if (c == cs->dup_cluster && cs->alloc_block) {
786 new_block = cs->alloc_block;
787 goto got_block;
788 }
789
790 if (ext2fs_test_block_bitmap2(ctx->block_dup_map, *block_nr)) {
f51b4d33
TT
791 n = dict_lookup(&clstr_dict,
792 INT_TO_VOIDPTR(EXT2FS_B2C(fs, *block_nr)));
793 if (!n) {
794 com_err("clone_file_block", 0,
795 _("internal error: can't find dup_blk for %llu\n"),
796 *block_nr);
797 return 0;
798 }
799
800 p = (struct dup_cluster *) dnode_get(n);
f51b4d33 801
f51b4d33 802 cs->dup_cluster = c;
9a1d614d
DW
803 /*
804 * Let's try an implied cluster allocation. If we get the same
805 * cluster back, then we need to find a new block; otherwise,
806 * we're merely fixing the problem of one logical cluster being
807 * mapped to multiple physical clusters.
808 */
809 new_block = 0;
bc1ec4b4
TT
810 retval = ext2fs_map_cluster_block(fs, cs->ino,
811 EXT2_INODE(cs->inode),
9a1d614d
DW
812 blockcnt, &new_block);
813 if (retval == 0 && new_block != 0 &&
814 EXT2FS_B2C(ctx->fs, new_block) !=
815 EXT2FS_B2C(ctx->fs, *block_nr))
816 goto cluster_alloc_ok;
f51b4d33
TT
817 retval = ext2fs_new_block2(fs, 0, ctx->block_found_map,
818 &new_block);
819 if (retval) {
820 cs->errcode = retval;
821 return BLOCK_ABORT;
822 }
9a1d614d 823cluster_alloc_ok:
f51b4d33
TT
824 cs->alloc_block = new_block;
825
826 got_block:
827 new_block &= ~EXT2FS_CLUSTER_MASK(fs);
828 new_block += EXT2FS_CLUSTER_MASK(fs) & blockcnt;
829 if (cs->dir && (blockcnt >= 0)) {
830 retval = ext2fs_set_dir_block2(fs->dblist,
831 cs->dir, new_block, blockcnt);
3839e657
TT
832 if (retval) {
833 cs->errcode = retval;
834 return BLOCK_ABORT;
835 }
f51b4d33 836 }
7b63fff9 837#if 0
f51b4d33
TT
838 printf("Cloning block #%lld from %llu to %llu\n",
839 blockcnt, *block_nr, new_block);
7b63fff9 840#endif
f51b4d33
TT
841 retval = io_channel_read_blk64(fs->io, *block_nr, 1, cs->buf);
842 if (retval) {
843 cs->errcode = retval;
844 return BLOCK_ABORT;
845 }
846 retval = io_channel_write_blk64(fs->io, new_block, 1, cs->buf);
847 if (retval) {
848 cs->errcode = retval;
849 return BLOCK_ABORT;
850 }
09282b8a
DW
851 cs->save_dup_cluster = (is_meta ? NULL : p);
852 cs->save_blocknr = *block_nr;
f51b4d33
TT
853 *block_nr = new_block;
854 ext2fs_mark_block_bitmap2(ctx->block_found_map, new_block);
855 ext2fs_mark_block_bitmap2(fs->block_map, new_block);
856 return BLOCK_CHANGED;
3839e657
TT
857 }
858 return 0;
859}
efc6f628 860
974d57d3
TT
861static errcode_t clone_file(e2fsck_t ctx, ext2_ino_t ino,
862 struct dup_inode *dp, char* block_buf)
3839e657 863{
1b6bf175 864 ext2_filsys fs = ctx->fs;
3839e657
TT
865 errcode_t retval;
866 struct clone_struct cs;
133a56dc 867 struct problem_context pctx;
a63745e8 868 blk64_t blk, new_blk;
838e773e
TT
869 dnode_t *n;
870 struct inode_el *ino_el;
f51b4d33 871 struct dup_cluster *dc;
838e773e 872 struct dup_inode *di;
3839e657 873
133a56dc 874 clear_problem_context(&pctx);
3839e657 875 cs.errcode = 0;
521e3685 876 cs.dir = 0;
b23f2f4d 877 cs.dup_cluster = ~0;
f51b4d33 878 cs.alloc_block = 0;
1b6bf175 879 cs.ctx = ctx;
9a1d614d
DW
880 cs.ino = ino;
881 cs.inode = &dp->inode;
09282b8a
DW
882 cs.save_dup_cluster = NULL;
883 cs.save_blocknr = 0;
c4e3d3f3 884 retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
08b21301
TT
885 if (retval)
886 return retval;
521e3685 887
c5d2f50d 888 if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, ino))
838e773e 889 cs.dir = ino;
133a56dc 890
838e773e 891 pctx.ino = ino;
133a56dc 892 pctx.str = "clone_file";
bc1ec4b4 893 if (ext2fs_inode_has_valid_blocks2(fs, EXT2_INODE(&dp->inode)))
a63745e8 894 pctx.errcode = ext2fs_block_iterate3(fs, ino, 0, block_buf,
0684a4f3 895 clone_file_block, &cs);
09282b8a 896 deferred_dec_badcount(&cs);
3839e657 897 ext2fs_mark_bb_dirty(fs);
133a56dc
TT
898 if (pctx.errcode) {
899 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
7abb2bdc
TT
900 retval = pctx.errcode;
901 goto errout;
3839e657
TT
902 }
903 if (cs.errcode) {
45ff69ff 904 com_err("clone_file", cs.errcode, "%s",
0c4a0726 905 _("returned from clone_file_block"));
7abb2bdc
TT
906 retval = cs.errcode;
907 goto errout;
3839e657 908 }
0684a4f3 909 /* The inode may have changed on disk, so we have to re-read it */
bc1ec4b4
TT
910 e2fsck_read_inode_full(ctx, ino, EXT2_INODE(&dp->inode),
911 sizeof(dp->inode), "clone file EA");
912 blk = ext2fs_file_acl_block(fs, EXT2_INODE(&dp->inode));
a63745e8
VAH
913 new_blk = blk;
914 if (blk && (clone_file_block(fs, &new_blk,
7abb2bdc
TT
915 BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
916 BLOCK_CHANGED)) {
bc1ec4b4
TT
917 ext2fs_file_acl_block_set(fs, EXT2_INODE(&dp->inode), new_blk);
918 e2fsck_write_inode_full(ctx, ino, EXT2_INODE(&dp->inode),
919 sizeof(dp->inode), "clone file EA");
342d847d
TT
920 /*
921 * If we cloned the EA block, find all other inodes
055866d8 922 * which referred to that EA block, and modify
342d847d
TT
923 * them to point to the new EA block.
924 */
f51b4d33
TT
925 n = dict_lookup(&clstr_dict,
926 INT_TO_VOIDPTR(EXT2FS_B2C(fs, blk)));
538e654c 927 if (!n) {
efc6f628 928 com_err("clone_file", 0,
538e654c 929 _("internal error: couldn't lookup EA "
a63745e8 930 "block record for %llu"), blk);
538e654c
BB
931 retval = 0; /* OK to stumble on... */
932 goto errout;
933 }
f51b4d33
TT
934 dc = (struct dup_cluster *) dnode_get(n);
935 for (ino_el = dc->inode_list; ino_el; ino_el = ino_el->next) {
838e773e 936 if (ino_el->inode == ino)
342d847d 937 continue;
0c193f82 938 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
538e654c 939 if (!n) {
efc6f628 940 com_err("clone_file", 0,
538e654c 941 _("internal error: couldn't lookup EA "
efc6f628 942 "inode record for %u"),
538e654c
BB
943 ino_el->inode);
944 retval = 0; /* OK to stumble on... */
945 goto errout;
946 }
838e773e 947 di = (struct dup_inode *) dnode_get(n);
bc1ec4b4
TT
948 if (ext2fs_file_acl_block(fs,
949 EXT2_INODE(&di->inode)) == blk) {
950 ext2fs_file_acl_block_set(fs,
951 EXT2_INODE(&di->inode),
952 ext2fs_file_acl_block(fs, EXT2_INODE(&dp->inode)));
953 e2fsck_write_inode_full(ctx, ino_el->inode,
954 EXT2_INODE(&di->inode),
955 sizeof(di->inode), "clone file EA");
f51b4d33 956 decrement_badcount(ctx, blk, dc);
7abb2bdc 957 }
342d847d
TT
958 }
959 }
7abb2bdc
TT
960 retval = 0;
961errout:
c4e3d3f3 962 ext2fs_free_mem(&cs.buf);
7abb2bdc 963 return retval;
3839e657 964}
80c5d7e4
TT
965
966/*
967 * This routine returns 1 if a block overlaps with one of the superblocks,
968 * group descriptors, inode bitmaps, or block bitmaps.
969 */
6dc64392 970static int check_if_fs_block(e2fsck_t ctx, blk64_t test_block)
80c5d7e4
TT
971{
972 ext2_filsys fs = ctx->fs;
6dc64392 973 blk64_t first_block;
54434927 974 dgrp_t i;
efc6f628 975
bb1a46a4 976 first_block = fs->super->s_first_data_block;
80c5d7e4
TT
977 for (i = 0; i < fs->group_desc_count; i++) {
978
bb1a46a4 979 /* Check superblocks/block group descriptors */
80c5d7e4 980 if (ext2fs_bg_has_super(fs, i)) {
bb1a46a4
ES
981 if (test_block >= first_block &&
982 (test_block <= first_block + fs->desc_blocks))
80c5d7e4
TT
983 return 1;
984 }
efc6f628 985
80c5d7e4 986 /* Check the inode table */
d7cca6b0
VAH
987 if ((ext2fs_inode_table_loc(fs, i)) &&
988 (test_block >= ext2fs_inode_table_loc(fs, i)) &&
989 (test_block < (ext2fs_inode_table_loc(fs, i) +
80c5d7e4
TT
990 fs->inode_blocks_per_group)))
991 return 1;
992
993 /* Check the bitmap blocks */
d7cca6b0
VAH
994 if ((test_block == ext2fs_block_bitmap_loc(fs, i)) ||
995 (test_block == ext2fs_inode_bitmap_loc(fs, i)))
80c5d7e4 996 return 1;
efc6f628 997
bb1a46a4 998 first_block += fs->super->s_blocks_per_group;
80c5d7e4
TT
999 }
1000 return 0;
1001}
f51b4d33
TT
1002
1003/*
1004 * This routine returns 1 if a cluster overlaps with one of the superblocks,
1005 * group descriptors, inode bitmaps, or block bitmaps.
1006 */
1007static int check_if_fs_cluster(e2fsck_t ctx, blk64_t cluster)
1008{
1009 ext2_filsys fs = ctx->fs;
1010 blk64_t first_block;
1011 dgrp_t i;
1012
1013 first_block = fs->super->s_first_data_block;
1014 for (i = 0; i < fs->group_desc_count; i++) {
1015
1016 /* Check superblocks/block group descriptors */
1017 if (ext2fs_bg_has_super(fs, i)) {
1018 if (cluster >= EXT2FS_B2C(fs, first_block) &&
1019 (cluster <= EXT2FS_B2C(fs, first_block +
1020 fs->desc_blocks)))
1021 return 1;
1022 }
1023
1024 /* Check the inode table */
1025 if ((ext2fs_inode_table_loc(fs, i)) &&
1026 (cluster >= EXT2FS_B2C(fs,
1027 ext2fs_inode_table_loc(fs, i))) &&
1028 (cluster <= EXT2FS_B2C(fs,
1029 ext2fs_inode_table_loc(fs, i) +
1030 fs->inode_blocks_per_group - 1)))
1031 return 1;
1032
1033 /* Check the bitmap blocks */
1034 if ((cluster == EXT2FS_B2C(fs,
1035 ext2fs_block_bitmap_loc(fs, i))) ||
1036 (cluster == EXT2FS_B2C(fs,
1037 ext2fs_inode_bitmap_loc(fs, i))))
1038 return 1;
1039
1040 first_block += fs->super->s_blocks_per_group;
1041 }
1042 return 0;
1043}