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