File: add_missing.c

package info (click to toggle)
reiser4progs 1.0.9-2
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 5,608 kB
  • ctags: 3,844
  • sloc: ansic: 33,541; sh: 10,679; makefile: 1,010
file content (372 lines) | stat: -rw-r--r-- 9,761 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
/*  Copyright 2001-2005 by Hans Reiser, licensing governed by 
    reiser4progs/COPYING.
    
    repair/add_missing.c -- the common methods for insertion leaves and extent
    item from twigs unconnected from the tree. */

#include <repair/add_missing.h>

/* Callback for item_ops->layout method to mark all the blocks, items points 
   to, in the allocator. */
static errno_t cb_item_mark_region(uint64_t start, uint64_t count, void *data) {
	repair_am_t *am = (repair_am_t *)data;
	
	aal_assert("vpf-735", data != NULL);
	
	if (start != 0) {
		/* These blocks are marked in allocator as it already has all 
		   blocks forbidden for allocation marked. Just mark them as 
		   used now. */
		reiser4_bitmap_mark_region(am->bm_used, start, count);
	}
	
	return 0;
}

/* Callback for traverse through all items of the node. Calls for the item, 
   determined by place, layout method, if it is not the branch and has pointers
   to some blocks. */
static errno_t cb_layout(reiser4_place_t *place, void *data) {
	aal_assert("vpf-649", place != NULL);
	aal_assert("vpf-748", !reiser4_item_branch(place->plug));

	if (!place->plug->object->layout)
		return 0;
	
	/* All these blocks should not be used in the allocator and should be 
	   forbidden for allocation. Check it somehow first. */
	return objcall(place, object->layout, cb_item_mark_region, data);
}

static void repair_add_missing_update(repair_am_t *am) {
	repair_am_stat_t *stat;
	aal_stream_t stream;
	char *time_str;
	
	aal_assert("vpf-886", am != NULL);
	
	stat = &am->stat;
	
	aal_stream_init(&stream, NULL, &memory_stream);
	
	aal_stream_format(&stream, "\tTwigs: read %llu, inserted %llu, "
			  "by item %llu, empty %llu\n", stat->read_twigs, 
			  stat->by_twig, stat->by_item_twigs,
			  stat->empty);
	
	aal_stream_format(&stream, "\tLeaves: read %llu, inserted %llu, by "
			  "item %llu\n", stat->read_leaves, stat->by_leaf, 
			  stat->by_item_leaves);

	time_str = ctime(&am->stat.time);
	time_str[aal_strlen(time_str) - 1] = '\0';
	aal_stream_format(&stream, "\tTime interval: %s - ", time_str);
	time(&am->stat.time);
	time_str = ctime(&am->stat.time);
	time_str[aal_strlen(time_str) - 1] = '\0';
	aal_stream_format(&stream, time_str);
	aal_mess(stream.entity);
	aal_stream_fini(&stream);
}

static errno_t repair_am_node_prepare(repair_am_t *am, reiser4_node_t *node) {
	reiser4_place_t place;
	trans_hint_t hint;
	uint32_t count;
	errno_t res;
	
	/* Remove all metadata items from the node before insertion. */
	place.node = node;
	place.pos.unit = MAX_UINT32;
	count = reiser4_node_items(node);

	for (place.pos.item = 0; place.pos.item < count; place.pos.item++) {
		if ((res = reiser4_place_fetch(&place))) {
			aal_error("Node (%llu), item (%u): failed to open the "
				  "item.",node->block->nr, place.pos.item);

			return res;
		}

		/* If this is an index item of the tree, remove it. */
		if (!reiser4_item_branch(place.plug)) 
			continue;

		hint.count = 1;
		hint.place_func = NULL;
		hint.region_func = NULL;
		hint.shift_flags = SF_DEFAULT;

		if ((res = reiser4_node_remove(place.node, &place.pos, &hint)))
			return res;

		place.pos.item--;
		count--;
	}
	
	return 0;
}

static errno_t repair_am_blk_free(repair_am_t *am, blk_t blk) {
	aal_assert("vpf-1330", am != NULL);

	return reiser4_alloc_release(am->repair->fs->alloc, blk, 1);
}

static errno_t repair_am_blk_used(repair_am_t *am, blk_t blk) {
	aal_assert("vpf-1330", am != NULL);

	/* These blocks are marked in allocator as it already has all blocks 
	   forbidden for allocation marked. Just mark them as used now. */
	reiser4_bitmap_mark_region(am->bm_used, blk, 1);

	return 0;
}

typedef struct stat_bitmap {
	uint64_t read, by_node, by_item, empty;
} stat_bitmap_t;

static errno_t repair_am_nodes_insert(repair_am_t *am, 
				      reiser4_bitmap_t *bitmap,
				      stat_bitmap_t *stat)
{
	reiser4_node_t *node;
	uint64_t total;
	errno_t res;
	blk_t blk;
	
	aal_assert("vpf-1282", am != NULL);
	aal_assert("vpf-1283", bitmap != NULL);
	aal_assert("vpf-1284", stat != NULL);
	
	total = reiser4_bitmap_marked(bitmap);
	
	blk = 0;
	/* Try to insert the whole twig/leaf at once. If it can be 
	   inserted only after splitting the node found by lookup 
	   into 2 nodes -- it will be done instead of following item
	   by item insertion. */
	while ((blk = reiser4_bitmap_find_marked(bitmap, blk)) != INVAL_BLK) {
		node = reiser4_node_open(am->repair->fs->tree, blk);
		stat->read++;
		aal_gauge_set_value(am->gauge, stat->read * 100 / total);
		aal_gauge_touch(am->gauge);

		if (node == NULL) {
			aal_error("Add Missing pass failed to "
				  "open the node (%llu)", blk);

			return -EINVAL;
		}

		/* Prepare the node for the insertion. */
		if ((res = repair_am_node_prepare(am, node))) 
			goto error_close_node;

		if (reiser4_node_items(node) == 0) {
			reiser4_bitmap_clear(bitmap, node->block->nr);
			repair_am_blk_free(am, node->block->nr);
			reiser4_node_close(node);
			stat->empty++;
			blk++;
			continue;
		}

		res = repair_tree_attach_node(am->repair->fs->tree, node);
		
		if (res < 0 && res != -ESTRUCT) {
			aal_error("Add missing pass failed to attach "
				  "the node (%llu) to the tree.", blk);

			goto error_close_node;
		} else if (res == 0) {
			/* Has been inserted. */
			reiser4_bitmap_clear(bitmap, node->block->nr);
			repair_am_blk_used(am, node->block->nr);

			stat->by_node++;

			res = reiser4_node_trav(node, cb_layout, am);
			if (res) goto error_close_node;

		} else {
			/* uninsertable case - insert by item later. */
			reiser4_node_fini(node);
		}
		
		blk++;
	}

	return 0;

 error_close_node:
	reiser4_node_close(node);
	return res;
}

static errno_t repair_am_items_insert(repair_am_t *am, 
				      reiser4_bitmap_t *bitmap, 
				      stat_bitmap_t *stat)
{
	uint32_t count;
	reiser4_node_t *node;
	uint64_t total;
	errno_t res;
	blk_t blk;

	aal_assert("vpf-1285", am != NULL);
	aal_assert("vpf-1286", bitmap != NULL);
	aal_assert("vpf-1287", stat != NULL);
	
	total = reiser4_bitmap_marked(bitmap);
	blk = 0;
	/* Insert extents from the twigs/all items from leaves which 
	   are not in the tree yet item-by-item into the tree, overwrite
	   existent data which is in the tree already if needed. 
	   FIXME: overwriting should be done on the base of flush_id. */
	while ((blk = reiser4_bitmap_find_marked(bitmap, blk)) != INVAL_BLK) {
		reiser4_place_t place;
		pos_t *pos = &place.pos;

		aal_assert("vpf-897", !reiser4_bitmap_test(am->bm_used, blk));

		node = reiser4_node_open(am->repair->fs->tree, blk);
		
		if (node == NULL) {
			aal_error("Add Missing pass failed to "
				  "open the node (%llu)", blk);
			return -EINVAL;
		}

		count = reiser4_node_items(node);
		place.node = node;

		stat->by_item++;
		aal_gauge_set_value(am->gauge, stat->by_item * 100 / total);
		aal_gauge_touch(am->gauge);

		for (pos->item = 0; pos->item < count; pos->item++) {
			pos->unit = MAX_UINT32;

			if ((res = reiser4_place_fetch(&place))) {
				aal_error("Node (%llu), item (%u): "
					  "cannot open the item "
					  "place.", blk, pos->item);

				goto error_close_node;
			}

			res = repair_tree_insert(am->repair->fs->tree, &place,
						 cb_item_mark_region, am);
			
			if (res < 0) 
				goto error_close_node;
			
			if (res && place.plug->p.id.group == STAT_ITEM) {
				/* If insertion cannot be performed for the 
				   statdata item, descement file counter. */
				(*am->stat.files)--;
			}
		}

		reiser4_bitmap_clear(bitmap, node->block->nr);
		repair_am_blk_free(am, node->block->nr);
		reiser4_node_close(node);
		blk++;
	}

	return 0;

 error_close_node:
	reiser4_node_close(node);
	return res;
}

/* The pass inself, adds all the data which are not in the tree yet and which 
   were found on the partition during the previous passes. */
errno_t repair_add_missing(repair_am_t *am) {
	reiser4_bitmap_t *bitmap;
	stat_bitmap_t stat;
	uint32_t bnum;
	errno_t res;
	
	aal_assert("vpf-595", am != NULL);
	aal_assert("vpf-846", am->repair != NULL);
	aal_assert("vpf-847", am->repair->fs != NULL);
	aal_assert("vpf-848", am->bm_twig != NULL);
	aal_assert("vpf-849", am->bm_leaf != NULL);
	
	aal_mess("INSERTING UNCONNECTED NODES");
	am->gauge = aal_gauge_create(aux_gauge_handlers[GT_PROGRESS], 
				     NULL, NULL, 500, NULL);
	time(&am->stat.time);
	
	/* 2 loops - 1 for twigs, another for leaves. */
	for (bnum = 0; bnum < 2; bnum++) {
		if (bnum) {
			bitmap = am->bm_leaf;
			aal_gauge_rename(am->gauge, "3. Leaves: ");
		} else {
			bitmap = am->bm_twig;
			aal_gauge_rename(am->gauge, "1. Twigs: ");
		}
		
		/* Debugging of item coping. */
		if (am->repair->flags & (1 << REPAIR_DEBUG)) 
			goto debug;
		
		aal_memset(&stat, 0, sizeof(stat));
		
		aal_gauge_set_value(am->gauge, 0);
		aal_gauge_touch(am->gauge);
		
		if ((res = repair_am_nodes_insert(am, bitmap, &stat)))
			goto error;
		
		if (bnum) {
			am->stat.read_leaves = stat.read;
			am->stat.by_leaf = stat.by_node;
		} else {
			am->stat.read_twigs = stat.read;
			am->stat.by_twig = stat.by_node;
			am->stat.empty = stat.empty;
		}
	
		aal_gauge_done(am->gauge);
	debug:
		if (bnum) {
			aal_gauge_rename(am->gauge, "4. Leaves by item: ");
		} else {
			aal_gauge_rename(am->gauge, "2. Twigs by item: ");
		} 
		
		aal_memset(&stat, 0, sizeof(stat));
		
		aal_gauge_set_value(am->gauge, 0);
		aal_gauge_touch(am->gauge);

		if ((res = repair_am_items_insert(am, bitmap, &stat)))
			goto error;

		if (bnum)
			am->stat.by_item_leaves = stat.by_item;
		else
			am->stat.by_item_twigs = stat.by_item;
		
		aal_gauge_done(am->gauge);
	}
	
	aal_gauge_free(am->gauge);
	repair_add_missing_update(am);
	reiser4_fs_sync(am->repair->fs);
	
	return 0;

 error:
	aal_gauge_done(am->gauge);
	aal_gauge_free(am->gauge);
	reiser4_fs_sync(am->repair->fs);
	return res;
}