blob: 4c4c78d002a4e0d81590a60557ec9a148583a22f [file] [log] [blame]
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00001/* vi: set sw=4 ts=4: */
2/*
3 * e2fsck
4 *
5 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
6 * Copyright (C) 2006 Garrett Kajmowicz
7 *
8 * Dictionary Abstract Data Type
9 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
10 * Free Software License:
11 * All rights are reserved by the author, with the following exceptions:
12 * Permission is granted to freely reproduce and distribute this software,
13 * possibly in exchange for a fee, provided that this copyright notice appears
14 * intact. Permission is also granted to adapt this software to produce
15 * derivative works, as long as the modified versions carry this copyright
16 * notice and additional notices stating that the work has been modified.
17 * This source code may be translated into executable form and incorporated
18 * into proprietary software; there is no requirement for such software to
19 * contain a copyright notice related to this source.
20 *
21 * linux/fs/recovery and linux/fs/revoke
22 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
23 *
24 * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
25 *
26 * Journal recovery routines for the generic filesystem journaling code;
27 * part of the ext2fs journaling system.
28 *
29 * Licensed under GPLv2 or later, see file License in this tarball for details.
30 */
31
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000032#include "e2fsck.h" /*Put all of our defines here to clean things up*/
33
34#define _(x) x
35#define N_(x) x
36
37/*
38 * Procedure declarations
39 */
40
41static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
42
43/* pass1.c */
44static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
45
46/* pass2.c */
47static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
48 ext2_ino_t ino, char *buf);
49
50/* pass3.c */
51static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
52static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
53 int num, int gauranteed_size);
54static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
55static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
56 int adj);
57
58/* rehash.c */
59static void e2fsck_rehash_directories(e2fsck_t ctx);
60
61/* util.c */
62static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
63 const char *description);
64static int ask(e2fsck_t ctx, const char * string, int def);
65static void e2fsck_read_bitmaps(e2fsck_t ctx);
66static void preenhalt(e2fsck_t ctx);
67static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
68 struct ext2_inode * inode, const char * proc);
69static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
70 struct ext2_inode * inode, const char * proc);
71static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
72 const char *name, io_manager manager);
73
74/* unix.c */
75static void e2fsck_clear_progbar(e2fsck_t ctx);
76static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
77 float percent, unsigned int dpynum);
78
79
80/*
81 * problem.h --- e2fsck problem error codes
82 */
83
84typedef __u32 problem_t;
85
86struct problem_context {
87 errcode_t errcode;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010088 ext2_ino_t ino, ino2, dir;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000089 struct ext2_inode *inode;
90 struct ext2_dir_entry *dirent;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010091 blk_t blk, blk2;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000092 e2_blkcnt_t blkcount;
93 int group;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010094 __u64 num;
95 const char *str;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000096};
97
98
99/*
100 * Function declarations
101 */
102static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
103static int end_problem_latch(e2fsck_t ctx, int mask);
104static int set_latch_flags(int mask, int setflags, int clearflags);
105static void clear_problem_context(struct problem_context *ctx);
106
107/*
108 * Dictionary Abstract Data Type
109 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
110 *
111 * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
112 * kazlib_1_20
113 */
114
115#ifndef DICT_H
116#define DICT_H
117
118/*
119 * Blurb for inclusion into C++ translation units
120 */
121
122typedef unsigned long dictcount_t;
123#define DICTCOUNT_T_MAX ULONG_MAX
124
125/*
126 * The dictionary is implemented as a red-black tree
127 */
128
129typedef enum { dnode_red, dnode_black } dnode_color_t;
130
131typedef struct dnode_t {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100132 struct dnode_t *dict_left;
133 struct dnode_t *dict_right;
134 struct dnode_t *dict_parent;
135 dnode_color_t dict_color;
136 const void *dict_key;
137 void *dict_data;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000138} dnode_t;
139
140typedef int (*dict_comp_t)(const void *, const void *);
141typedef void (*dnode_free_t)(dnode_t *);
142
143typedef struct dict_t {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100144 dnode_t dict_nilnode;
145 dictcount_t dict_nodecount;
146 dictcount_t dict_maxcount;
147 dict_comp_t dict_compare;
148 dnode_free_t dict_freenode;
149 int dict_dupes;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000150} dict_t;
151
152typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
153
154typedef struct dict_load_t {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100155 dict_t *dict_dictptr;
156 dnode_t dict_nilnode;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000157} dict_load_t;
158
159#define dict_count(D) ((D)->dict_nodecount)
160#define dnode_get(N) ((N)->dict_data)
161#define dnode_getkey(N) ((N)->dict_key)
162
163#endif
164
165/*
166 * Compatibility header file for e2fsck which should be included
167 * instead of linux/jfs.h
168 *
169 * Copyright (C) 2000 Stephen C. Tweedie
170 */
171
172/*
173 * Pull in the definition of the e2fsck context structure
174 */
175
176struct buffer_head {
177 char b_data[8192];
178 e2fsck_t b_ctx;
179 io_channel b_io;
180 int b_size;
181 blk_t b_blocknr;
182 int b_dirty;
183 int b_uptodate;
184 int b_err;
185};
186
187
188#define K_DEV_FS 1
189#define K_DEV_JOURNAL 2
190
Denis Vlasenkobb045062008-09-27 14:06:06 +0000191#define lock_buffer(bh) do {} while (0)
192#define unlock_buffer(bh) do {} while (0)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000193#define buffer_req(bh) 1
Denis Vlasenkobb045062008-09-27 14:06:06 +0000194#define do_readahead(journal, start) do {} while (0)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000195
196static e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
197
198typedef struct {
199 int object_length;
200} kmem_cache_t;
201
202#define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
203
204/*
205 * We use the standard libext2fs portability tricks for inline
206 * functions.
207 */
208
209static kmem_cache_t * do_cache_create(int len)
210{
211 kmem_cache_t *new_cache;
212
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100213 new_cache = xmalloc(sizeof(*new_cache));
214 new_cache->object_length = len;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000215 return new_cache;
216}
217
218static void do_cache_destroy(kmem_cache_t *cache)
219{
220 free(cache);
221}
222
223
224/*
225 * Dictionary Abstract Data Type
226 */
227
228
229/*
230 * These macros provide short convenient names for structure members,
231 * which are embellished with dict_ prefixes so that they are
232 * properly confined to the documented namespace. It's legal for a
233 * program which uses dict to define, for instance, a macro called ``parent''.
234 * Such a macro would interfere with the dnode_t struct definition.
235 * In general, highly portable and reusable C modules which expose their
236 * structures need to confine structure member names to well-defined spaces.
237 * The resulting identifiers aren't necessarily convenient to use, nor
238 * readable, in the implementation, however!
239 */
240
241#define left dict_left
242#define right dict_right
243#define parent dict_parent
244#define color dict_color
245#define key dict_key
246#define data dict_data
247
248#define nilnode dict_nilnode
249#define maxcount dict_maxcount
250#define compare dict_compare
251#define dupes dict_dupes
252
253#define dict_root(D) ((D)->nilnode.left)
254#define dict_nil(D) (&(D)->nilnode)
255
256static void dnode_free(dnode_t *node);
257
258/*
259 * Perform a ``left rotation'' adjustment on the tree. The given node P and
260 * its right child C are rearranged so that the P instead becomes the left
261 * child of C. The left subtree of C is inherited as the new right subtree
262 * for P. The ordering of the keys within the tree is thus preserved.
263 */
264
265static void rotate_left(dnode_t *upper)
266{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100267 dnode_t *lower, *lowleft, *upparent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000268
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100269 lower = upper->right;
270 upper->right = lowleft = lower->left;
271 lowleft->parent = upper;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000272
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100273 lower->parent = upparent = upper->parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000274
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100275 /* don't need to check for root node here because root->parent is
276 the sentinel nil node, and root->parent->left points back to root */
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000277
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100278 if (upper == upparent->left) {
279 upparent->left = lower;
280 } else {
281 assert (upper == upparent->right);
282 upparent->right = lower;
283 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000284
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100285 lower->left = upper;
286 upper->parent = lower;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000287}
288
289/*
290 * This operation is the ``mirror'' image of rotate_left. It is
291 * the same procedure, but with left and right interchanged.
292 */
293
294static void rotate_right(dnode_t *upper)
295{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100296 dnode_t *lower, *lowright, *upparent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000297
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100298 lower = upper->left;
299 upper->left = lowright = lower->right;
300 lowright->parent = upper;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000301
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100302 lower->parent = upparent = upper->parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000303
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100304 if (upper == upparent->right) {
305 upparent->right = lower;
306 } else {
307 assert (upper == upparent->left);
308 upparent->left = lower;
309 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000310
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100311 lower->right = upper;
312 upper->parent = lower;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000313}
314
315/*
316 * Do a postorder traversal of the tree rooted at the specified
317 * node and free everything under it. Used by dict_free().
318 */
319
320static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
321{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100322 if (node == nil)
323 return;
324 free_nodes(dict, node->left, nil);
325 free_nodes(dict, node->right, nil);
326 dict->dict_freenode(node);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000327}
328
329/*
330 * Verify that the tree contains the given node. This is done by
331 * traversing all of the nodes and comparing their pointers to the
332 * given pointer. Returns 1 if the node is found, otherwise
333 * returns zero. It is intended for debugging purposes.
334 */
335
336static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
337{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100338 if (root != nil) {
339 return root == node
340 || verify_dict_has_node(nil, root->left, node)
341 || verify_dict_has_node(nil, root->right, node);
342 }
343 return 0;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000344}
345
346
347/*
348 * Select a different set of node allocator routines.
349 */
350
351static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
352{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100353 assert(dict_count(dict) == 0);
354 dict->dict_freenode = fr;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000355}
356
357/*
358 * Free all the nodes in the dictionary by using the dictionary's
359 * installed free routine. The dictionary is emptied.
360 */
361
362static void dict_free_nodes(dict_t *dict)
363{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100364 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
365 free_nodes(dict, root, nil);
366 dict->dict_nodecount = 0;
367 dict->nilnode.left = &dict->nilnode;
368 dict->nilnode.right = &dict->nilnode;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000369}
370
371/*
372 * Initialize a user-supplied dictionary object.
373 */
374
375static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
376{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100377 dict->compare = comp;
378 dict->dict_freenode = dnode_free;
379 dict->dict_nodecount = 0;
380 dict->maxcount = maxcount;
381 dict->nilnode.left = &dict->nilnode;
382 dict->nilnode.right = &dict->nilnode;
383 dict->nilnode.parent = &dict->nilnode;
384 dict->nilnode.color = dnode_black;
385 dict->dupes = 0;
386 return dict;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000387}
388
389/*
390 * Locate a node in the dictionary having the given key.
391 * If the node is not found, a null a pointer is returned (rather than
392 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
393 * located node is returned.
394 */
395
396static dnode_t *dict_lookup(dict_t *dict, const void *key)
397{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100398 dnode_t *root = dict_root(dict);
399 dnode_t *nil = dict_nil(dict);
400 dnode_t *saved;
401 int result;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000402
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100403 /* simple binary search adapted for trees that contain duplicate keys */
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000404
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100405 while (root != nil) {
406 result = dict->compare(key, root->key);
407 if (result < 0)
408 root = root->left;
409 else if (result > 0)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000410 root = root->right;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100411 else {
412 if (!dict->dupes) { /* no duplicates, return match */
413 return root;
414 } else { /* could be dupes, find leftmost one */
415 do {
416 saved = root;
417 root = root->left;
418 while (root != nil && dict->compare(key, root->key))
419 root = root->right;
420 } while (root != nil);
421 return saved;
422 }
423 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000424 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000425
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100426 return NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000427}
428
429/*
430 * Insert a node into the dictionary. The node should have been
431 * initialized with a data field. All other fields are ignored.
432 * The behavior is undefined if the user attempts to insert into
433 * a dictionary that is already full (for which the dict_isfull()
434 * function returns true).
435 */
436
437static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
438{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100439 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
440 dnode_t *parent = nil, *uncle, *grandpa;
441 int result = -1;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000442
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100443 node->key = key;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000444
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100445 /* basic binary tree insert */
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000446
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100447 while (where != nil) {
448 parent = where;
449 result = dict->compare(key, where->key);
450 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
451 assert(dict->dupes || result != 0);
452 if (result < 0)
453 where = where->left;
454 else
455 where = where->right;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000456 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000457
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100458 assert(where == nil);
459
460 if (result < 0)
461 parent->left = node;
462 else
463 parent->right = node;
464
465 node->parent = parent;
466 node->left = nil;
467 node->right = nil;
468
469 dict->dict_nodecount++;
470
471 /* red black adjustments */
472
473 node->color = dnode_red;
474
475 while (parent->color == dnode_red) {
476 grandpa = parent->parent;
477 if (parent == grandpa->left) {
478 uncle = grandpa->right;
479 if (uncle->color == dnode_red) { /* red parent, red uncle */
480 parent->color = dnode_black;
481 uncle->color = dnode_black;
482 grandpa->color = dnode_red;
483 node = grandpa;
484 parent = grandpa->parent;
485 } else { /* red parent, black uncle */
486 if (node == parent->right) {
487 rotate_left(parent);
488 parent = node;
489 assert (grandpa == parent->parent);
490 /* rotation between parent and child preserves grandpa */
491 }
492 parent->color = dnode_black;
493 grandpa->color = dnode_red;
494 rotate_right(grandpa);
495 break;
496 }
497 } else { /* symmetric cases: parent == parent->parent->right */
498 uncle = grandpa->left;
499 if (uncle->color == dnode_red) {
500 parent->color = dnode_black;
501 uncle->color = dnode_black;
502 grandpa->color = dnode_red;
503 node = grandpa;
504 parent = grandpa->parent;
505 } else {
506 if (node == parent->left) {
507 rotate_right(parent);
508 parent = node;
509 assert (grandpa == parent->parent);
510 }
511 parent->color = dnode_black;
512 grandpa->color = dnode_red;
513 rotate_left(grandpa);
514 break;
515 }
516 }
517 }
518
519 dict_root(dict)->color = dnode_black;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000520
521}
522
523/*
524 * Allocate a node using the dictionary's allocator routine, give it
525 * the data item.
526 */
527
528static dnode_t *dnode_init(dnode_t *dnode, void *data)
529{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100530 dnode->data = data;
531 dnode->parent = NULL;
532 dnode->left = NULL;
533 dnode->right = NULL;
534 return dnode;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000535}
536
537static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
538{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100539 dnode_t *node = xmalloc(sizeof(dnode_t));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000540
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000541 dnode_init(node, data);
542 dict_insert(dict, node, key);
543 return 1;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000544}
545
546/*
547 * Return the node with the lowest (leftmost) key. If the dictionary is empty
548 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
549 */
550
551static dnode_t *dict_first(dict_t *dict)
552{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100553 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000554
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100555 if (root != nil)
556 while ((left = root->left) != nil)
557 root = left;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000558
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100559 return (root == nil) ? NULL : root;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000560}
561
562/*
563 * Return the given node's successor node---the node which has the
564 * next key in the the left to right ordering. If the node has
565 * no successor, a null pointer is returned rather than a pointer to
566 * the nil node.
567 */
568
569static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
570{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100571 dnode_t *nil = dict_nil(dict), *parent, *left;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000572
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100573 if (curr->right != nil) {
574 curr = curr->right;
575 while ((left = curr->left) != nil)
576 curr = left;
577 return curr;
578 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000579
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000580 parent = curr->parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000581
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100582 while (parent != nil && curr == parent->right) {
583 curr = parent;
584 parent = curr->parent;
585 }
586
587 return (parent == nil) ? NULL : parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000588}
589
590
591static void dnode_free(dnode_t *node)
592{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100593 free(node);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000594}
595
596
597#undef left
598#undef right
599#undef parent
600#undef color
601#undef key
602#undef data
603
604#undef nilnode
605#undef maxcount
606#undef compare
607#undef dupes
608
609
610/*
611 * dirinfo.c --- maintains the directory information table for e2fsck.
612 */
613
614/*
615 * This subroutine is called during pass1 to create a directory info
616 * entry. During pass1, the passed-in parent is 0; it will get filled
617 * in during pass2.
618 */
619static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
620{
621 struct dir_info *dir;
622 int i, j;
623 ext2_ino_t num_dirs;
624 errcode_t retval;
625 unsigned long old_size;
626
627 if (!ctx->dir_info) {
628 ctx->dir_info_count = 0;
629 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
630 if (retval)
631 num_dirs = 1024; /* Guess */
632 ctx->dir_info_size = num_dirs + 10;
633 ctx->dir_info = (struct dir_info *)
634 e2fsck_allocate_memory(ctx, ctx->dir_info_size
635 * sizeof (struct dir_info),
636 "directory map");
637 }
638
639 if (ctx->dir_info_count >= ctx->dir_info_size) {
640 old_size = ctx->dir_info_size * sizeof(struct dir_info);
641 ctx->dir_info_size += 10;
642 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
643 sizeof(struct dir_info),
644 &ctx->dir_info);
645 if (retval) {
646 ctx->dir_info_size -= 10;
647 return;
648 }
649 }
650
651 /*
652 * Normally, add_dir_info is called with each inode in
653 * sequential order; but once in a while (like when pass 3
654 * needs to recreate the root directory or lost+found
655 * directory) it is called out of order. In those cases, we
656 * need to move the dir_info entries down to make room, since
657 * the dir_info array needs to be sorted by inode number for
658 * get_dir_info()'s sake.
659 */
660 if (ctx->dir_info_count &&
661 ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
662 for (i = ctx->dir_info_count-1; i > 0; i--)
663 if (ctx->dir_info[i-1].ino < ino)
664 break;
665 dir = &ctx->dir_info[i];
666 if (dir->ino != ino)
667 for (j = ctx->dir_info_count++; j > i; j--)
668 ctx->dir_info[j] = ctx->dir_info[j-1];
669 } else
670 dir = &ctx->dir_info[ctx->dir_info_count++];
671
672 dir->ino = ino;
673 dir->dotdot = parent;
674 dir->parent = parent;
675}
676
677/*
678 * get_dir_info() --- given an inode number, try to find the directory
679 * information entry for it.
680 */
681static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
682{
683 int low, high, mid;
684
685 low = 0;
686 high = ctx->dir_info_count-1;
687 if (!ctx->dir_info)
688 return 0;
689 if (ino == ctx->dir_info[low].ino)
690 return &ctx->dir_info[low];
691 if (ino == ctx->dir_info[high].ino)
692 return &ctx->dir_info[high];
693
694 while (low < high) {
695 mid = (low+high)/2;
696 if (mid == low || mid == high)
697 break;
698 if (ino == ctx->dir_info[mid].ino)
699 return &ctx->dir_info[mid];
700 if (ino < ctx->dir_info[mid].ino)
701 high = mid;
702 else
703 low = mid;
704 }
705 return 0;
706}
707
708/*
709 * Free the dir_info structure when it isn't needed any more.
710 */
711static void e2fsck_free_dir_info(e2fsck_t ctx)
712{
713 ext2fs_free_mem(&ctx->dir_info);
714 ctx->dir_info_size = 0;
715 ctx->dir_info_count = 0;
716}
717
718/*
719 * Return the count of number of directories in the dir_info structure
720 */
721static int e2fsck_get_num_dirinfo(e2fsck_t ctx)
722{
723 return ctx->dir_info_count;
724}
725
726/*
727 * A simple interator function
728 */
729static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
730{
731 if (*control >= ctx->dir_info_count)
732 return 0;
733
734 return ctx->dir_info + (*control)++;
735}
736
737/*
738 * dirinfo.c --- maintains the directory information table for e2fsck.
739 *
740 */
741
742#ifdef ENABLE_HTREE
743
744/*
745 * This subroutine is called during pass1 to create a directory info
746 * entry. During pass1, the passed-in parent is 0; it will get filled
747 * in during pass2.
748 */
749static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
750{
751 struct dx_dir_info *dir;
752 int i, j;
753 errcode_t retval;
754 unsigned long old_size;
755
756 if (!ctx->dx_dir_info) {
757 ctx->dx_dir_info_count = 0;
758 ctx->dx_dir_info_size = 100; /* Guess */
759 ctx->dx_dir_info = (struct dx_dir_info *)
760 e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
761 * sizeof (struct dx_dir_info),
762 "directory map");
763 }
764
765 if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
766 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
767 ctx->dx_dir_info_size += 10;
768 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
769 sizeof(struct dx_dir_info),
770 &ctx->dx_dir_info);
771 if (retval) {
772 ctx->dx_dir_info_size -= 10;
773 return;
774 }
775 }
776
777 /*
778 * Normally, add_dx_dir_info is called with each inode in
779 * sequential order; but once in a while (like when pass 3
780 * needs to recreate the root directory or lost+found
781 * directory) it is called out of order. In those cases, we
782 * need to move the dx_dir_info entries down to make room, since
783 * the dx_dir_info array needs to be sorted by inode number for
784 * get_dx_dir_info()'s sake.
785 */
786 if (ctx->dx_dir_info_count &&
787 ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
788 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
789 if (ctx->dx_dir_info[i-1].ino < ino)
790 break;
791 dir = &ctx->dx_dir_info[i];
792 if (dir->ino != ino)
793 for (j = ctx->dx_dir_info_count++; j > i; j--)
794 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
795 } else
796 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
797
798 dir->ino = ino;
799 dir->numblocks = num_blocks;
800 dir->hashversion = 0;
801 dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
802 * sizeof (struct dx_dirblock_info),
803 "dx_block info array");
804
805}
806
807/*
808 * get_dx_dir_info() --- given an inode number, try to find the directory
809 * information entry for it.
810 */
811static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
812{
813 int low, high, mid;
814
815 low = 0;
816 high = ctx->dx_dir_info_count-1;
817 if (!ctx->dx_dir_info)
818 return 0;
819 if (ino == ctx->dx_dir_info[low].ino)
820 return &ctx->dx_dir_info[low];
821 if (ino == ctx->dx_dir_info[high].ino)
822 return &ctx->dx_dir_info[high];
823
824 while (low < high) {
825 mid = (low+high)/2;
826 if (mid == low || mid == high)
827 break;
828 if (ino == ctx->dx_dir_info[mid].ino)
829 return &ctx->dx_dir_info[mid];
830 if (ino < ctx->dx_dir_info[mid].ino)
831 high = mid;
832 else
833 low = mid;
834 }
835 return 0;
836}
837
838/*
839 * Free the dx_dir_info structure when it isn't needed any more.
840 */
841static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
842{
843 int i;
844 struct dx_dir_info *dir;
845
846 if (ctx->dx_dir_info) {
847 dir = ctx->dx_dir_info;
848 for (i=0; i < ctx->dx_dir_info_count; i++) {
849 ext2fs_free_mem(&dir->dx_block);
850 }
851 ext2fs_free_mem(&ctx->dx_dir_info);
852 }
853 ctx->dx_dir_info_size = 0;
854 ctx->dx_dir_info_count = 0;
855}
856
857/*
858 * A simple interator function
859 */
860static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
861{
862 if (*control >= ctx->dx_dir_info_count)
863 return 0;
864
865 return ctx->dx_dir_info + (*control)++;
866}
867
868#endif /* ENABLE_HTREE */
869/*
870 * e2fsck.c - a consistency checker for the new extended file system.
871 *
872 */
873
874/*
875 * This function allocates an e2fsck context
876 */
877static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
878{
879 e2fsck_t context;
880 errcode_t retval;
881
882 retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
883 if (retval)
884 return retval;
885
886 memset(context, 0, sizeof(struct e2fsck_struct));
887
888 context->process_inode_size = 256;
889 context->ext_attr_ver = 2;
890
891 *ret = context;
892 return 0;
893}
894
895struct ea_refcount_el {
896 blk_t ea_blk;
897 int ea_count;
898};
899
900struct ea_refcount {
901 blk_t count;
902 blk_t size;
903 blk_t cursor;
904 struct ea_refcount_el *list;
905};
906
907static void ea_refcount_free(ext2_refcount_t refcount)
908{
909 if (!refcount)
910 return;
911
912 ext2fs_free_mem(&refcount->list);
913 ext2fs_free_mem(&refcount);
914}
915
916/*
917 * This function resets an e2fsck context; it is called when e2fsck
918 * needs to be restarted.
919 */
920static errcode_t e2fsck_reset_context(e2fsck_t ctx)
921{
922 ctx->flags = 0;
923 ctx->lost_and_found = 0;
924 ctx->bad_lost_and_found = 0;
925 ext2fs_free_inode_bitmap(ctx->inode_used_map);
926 ctx->inode_used_map = 0;
927 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
928 ctx->inode_dir_map = 0;
929 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
930 ctx->inode_reg_map = 0;
931 ext2fs_free_block_bitmap(ctx->block_found_map);
932 ctx->block_found_map = 0;
933 ext2fs_free_icount(ctx->inode_link_info);
934 ctx->inode_link_info = 0;
935 if (ctx->journal_io) {
936 if (ctx->fs && ctx->fs->io != ctx->journal_io)
937 io_channel_close(ctx->journal_io);
938 ctx->journal_io = 0;
939 }
940 if (ctx->fs) {
941 ext2fs_free_dblist(ctx->fs->dblist);
942 ctx->fs->dblist = 0;
943 }
944 e2fsck_free_dir_info(ctx);
945#ifdef ENABLE_HTREE
946 e2fsck_free_dx_dir_info(ctx);
947#endif
948 ea_refcount_free(ctx->refcount);
949 ctx->refcount = 0;
950 ea_refcount_free(ctx->refcount_extra);
951 ctx->refcount_extra = 0;
952 ext2fs_free_block_bitmap(ctx->block_dup_map);
953 ctx->block_dup_map = 0;
954 ext2fs_free_block_bitmap(ctx->block_ea_map);
955 ctx->block_ea_map = 0;
956 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
957 ctx->inode_bad_map = 0;
958 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
959 ctx->inode_imagic_map = 0;
960 ext2fs_u32_list_free(ctx->dirs_to_hash);
961 ctx->dirs_to_hash = 0;
962
963 /*
964 * Clear the array of invalid meta-data flags
965 */
966 ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
967 ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
968 ext2fs_free_mem(&ctx->invalid_inode_table_flag);
969
970 /* Clear statistic counters */
971 ctx->fs_directory_count = 0;
972 ctx->fs_regular_count = 0;
973 ctx->fs_blockdev_count = 0;
974 ctx->fs_chardev_count = 0;
975 ctx->fs_links_count = 0;
976 ctx->fs_symlinks_count = 0;
977 ctx->fs_fast_symlinks_count = 0;
978 ctx->fs_fifo_count = 0;
979 ctx->fs_total_count = 0;
980 ctx->fs_sockets_count = 0;
981 ctx->fs_ind_count = 0;
982 ctx->fs_dind_count = 0;
983 ctx->fs_tind_count = 0;
984 ctx->fs_fragmented = 0;
985 ctx->large_files = 0;
986
987 /* Reset the superblock to the user's requested value */
988 ctx->superblock = ctx->use_superblock;
989
990 return 0;
991}
992
993static void e2fsck_free_context(e2fsck_t ctx)
994{
995 if (!ctx)
996 return;
997
998 e2fsck_reset_context(ctx);
999 if (ctx->blkid)
1000 blkid_put_cache(ctx->blkid);
1001
1002 ext2fs_free_mem(&ctx);
1003}
1004
1005/*
1006 * ea_refcount.c
1007 */
1008
1009/*
1010 * The strategy we use for keeping track of EA refcounts is as
1011 * follows. We keep a sorted array of first EA blocks and its
1012 * reference counts. Once the refcount has dropped to zero, it is
1013 * removed from the array to save memory space. Once the EA block is
1014 * checked, its bit is set in the block_ea_map bitmap.
1015 */
1016
1017
1018static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
1019{
1020 ext2_refcount_t refcount;
1021 errcode_t retval;
1022 size_t bytes;
1023
1024 retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
1025 if (retval)
1026 return retval;
1027 memset(refcount, 0, sizeof(struct ea_refcount));
1028
1029 if (!size)
1030 size = 500;
1031 refcount->size = size;
1032 bytes = (size_t) (size * sizeof(struct ea_refcount_el));
1033#ifdef DEBUG
1034 printf("Refcount allocated %d entries, %d bytes.\n",
1035 refcount->size, bytes);
1036#endif
1037 retval = ext2fs_get_mem(bytes, &refcount->list);
1038 if (retval)
1039 goto errout;
1040 memset(refcount->list, 0, bytes);
1041
1042 refcount->count = 0;
1043 refcount->cursor = 0;
1044
1045 *ret = refcount;
1046 return 0;
1047
1048errout:
1049 ea_refcount_free(refcount);
1050 return retval;
1051}
1052
1053/*
1054 * collapse_refcount() --- go through the refcount array, and get rid
1055 * of any count == zero entries
1056 */
1057static void refcount_collapse(ext2_refcount_t refcount)
1058{
1059 unsigned int i, j;
1060 struct ea_refcount_el *list;
1061
1062 list = refcount->list;
1063 for (i = 0, j = 0; i < refcount->count; i++) {
1064 if (list[i].ea_count) {
1065 if (i != j)
1066 list[j] = list[i];
1067 j++;
1068 }
1069 }
1070#if defined(DEBUG) || defined(TEST_PROGRAM)
1071 printf("Refcount_collapse: size was %d, now %d\n",
1072 refcount->count, j);
1073#endif
1074 refcount->count = j;
1075}
1076
1077
1078/*
1079 * insert_refcount_el() --- Insert a new entry into the sorted list at a
1080 * specified position.
1081 */
1082static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
1083 blk_t blk, int pos)
1084{
1085 struct ea_refcount_el *el;
1086 errcode_t retval;
1087 blk_t new_size = 0;
1088 int num;
1089
1090 if (refcount->count >= refcount->size) {
1091 new_size = refcount->size + 100;
1092#ifdef DEBUG
1093 printf("Reallocating refcount %d entries...\n", new_size);
1094#endif
1095 retval = ext2fs_resize_mem((size_t) refcount->size *
1096 sizeof(struct ea_refcount_el),
1097 (size_t) new_size *
1098 sizeof(struct ea_refcount_el),
1099 &refcount->list);
1100 if (retval)
1101 return 0;
1102 refcount->size = new_size;
1103 }
1104 num = (int) refcount->count - pos;
1105 if (num < 0)
1106 return 0; /* should never happen */
1107 if (num) {
1108 memmove(&refcount->list[pos+1], &refcount->list[pos],
1109 sizeof(struct ea_refcount_el) * num);
1110 }
1111 refcount->count++;
1112 el = &refcount->list[pos];
1113 el->ea_count = 0;
1114 el->ea_blk = blk;
1115 return el;
1116}
1117
1118
1119/*
1120 * get_refcount_el() --- given an block number, try to find refcount
1121 * information in the sorted list. If the create flag is set,
1122 * and we can't find an entry, create one in the sorted list.
1123 */
1124static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
1125 blk_t blk, int create)
1126{
1127 float range;
1128 int low, high, mid;
1129 blk_t lowval, highval;
1130
1131 if (!refcount || !refcount->list)
1132 return 0;
1133retry:
1134 low = 0;
1135 high = (int) refcount->count-1;
1136 if (create && ((refcount->count == 0) ||
1137 (blk > refcount->list[high].ea_blk))) {
1138 if (refcount->count >= refcount->size)
1139 refcount_collapse(refcount);
1140
1141 return insert_refcount_el(refcount, blk,
1142 (unsigned) refcount->count);
1143 }
1144 if (refcount->count == 0)
1145 return 0;
1146
1147 if (refcount->cursor >= refcount->count)
1148 refcount->cursor = 0;
1149 if (blk == refcount->list[refcount->cursor].ea_blk)
1150 return &refcount->list[refcount->cursor++];
1151#ifdef DEBUG
1152 printf("Non-cursor get_refcount_el: %u\n", blk);
1153#endif
1154 while (low <= high) {
1155 if (low == high)
1156 mid = low;
1157 else {
1158 /* Interpolate for efficiency */
1159 lowval = refcount->list[low].ea_blk;
1160 highval = refcount->list[high].ea_blk;
1161
1162 if (blk < lowval)
1163 range = 0;
1164 else if (blk > highval)
1165 range = 1;
1166 else
1167 range = ((float) (blk - lowval)) /
1168 (highval - lowval);
1169 mid = low + ((int) (range * (high-low)));
1170 }
1171
1172 if (blk == refcount->list[mid].ea_blk) {
1173 refcount->cursor = mid+1;
1174 return &refcount->list[mid];
1175 }
1176 if (blk < refcount->list[mid].ea_blk)
1177 high = mid-1;
1178 else
1179 low = mid+1;
1180 }
1181 /*
1182 * If we need to create a new entry, it should be right at
1183 * low (where high will be left at low-1).
1184 */
1185 if (create) {
1186 if (refcount->count >= refcount->size) {
1187 refcount_collapse(refcount);
1188 if (refcount->count < refcount->size)
1189 goto retry;
1190 }
1191 return insert_refcount_el(refcount, blk, low);
1192 }
1193 return 0;
1194}
1195
1196static errcode_t
1197ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
1198{
1199 struct ea_refcount_el *el;
1200
1201 el = get_refcount_el(refcount, blk, 1);
1202 if (!el)
1203 return EXT2_ET_NO_MEMORY;
1204 el->ea_count++;
1205
1206 if (ret)
1207 *ret = el->ea_count;
1208 return 0;
1209}
1210
1211static errcode_t
1212ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
1213{
1214 struct ea_refcount_el *el;
1215
1216 el = get_refcount_el(refcount, blk, 0);
1217 if (!el || el->ea_count == 0)
1218 return EXT2_ET_INVALID_ARGUMENT;
1219
1220 el->ea_count--;
1221
1222 if (ret)
1223 *ret = el->ea_count;
1224 return 0;
1225}
1226
1227static errcode_t
1228ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
1229{
1230 struct ea_refcount_el *el;
1231
1232 /*
1233 * Get the refcount element
1234 */
1235 el = get_refcount_el(refcount, blk, count ? 1 : 0);
1236 if (!el)
1237 return count ? EXT2_ET_NO_MEMORY : 0;
1238 el->ea_count = count;
1239 return 0;
1240}
1241
1242static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
1243{
1244 refcount->cursor = 0;
1245}
1246
1247
1248static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
1249{
1250 struct ea_refcount_el *list;
1251
1252 while (1) {
1253 if (refcount->cursor >= refcount->count)
1254 return 0;
1255 list = refcount->list;
1256 if (list[refcount->cursor].ea_count) {
1257 if (ret)
1258 *ret = list[refcount->cursor].ea_count;
1259 return list[refcount->cursor++].ea_blk;
1260 }
1261 refcount->cursor++;
1262 }
1263}
1264
1265
1266/*
1267 * ehandler.c --- handle bad block errors which come up during the
1268 * course of an e2fsck session.
1269 */
1270
1271
1272static const char *operation;
1273
1274static errcode_t
1275e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
1276 void *data, size_t size FSCK_ATTR((unused)),
1277 int actual FSCK_ATTR((unused)), errcode_t error)
1278{
1279 int i;
1280 char *p;
1281 ext2_filsys fs = (ext2_filsys) channel->app_data;
1282 e2fsck_t ctx;
1283
1284 ctx = (e2fsck_t) fs->priv_data;
1285
1286 /*
1287 * If more than one block was read, try reading each block
1288 * separately. We could use the actual bytes read to figure
1289 * out where to start, but we don't bother.
1290 */
1291 if (count > 1) {
1292 p = (char *) data;
1293 for (i=0; i < count; i++, p += channel->block_size, block++) {
1294 error = io_channel_read_blk(channel, block,
1295 1, p);
1296 if (error)
1297 return error;
1298 }
1299 return 0;
1300 }
1301 if (operation)
1302 printf(_("Error reading block %lu (%s) while %s. "), block,
1303 error_message(error), operation);
1304 else
1305 printf(_("Error reading block %lu (%s). "), block,
1306 error_message(error));
1307 preenhalt(ctx);
1308 if (ask(ctx, _("Ignore error"), 1)) {
1309 if (ask(ctx, _("Force rewrite"), 1))
1310 io_channel_write_blk(channel, block, 1, data);
1311 return 0;
1312 }
1313
1314 return error;
1315}
1316
1317static errcode_t
1318e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
1319 const void *data, size_t size FSCK_ATTR((unused)),
1320 int actual FSCK_ATTR((unused)), errcode_t error)
1321{
1322 int i;
1323 const char *p;
1324 ext2_filsys fs = (ext2_filsys) channel->app_data;
1325 e2fsck_t ctx;
1326
1327 ctx = (e2fsck_t) fs->priv_data;
1328
1329 /*
1330 * If more than one block was written, try writing each block
1331 * separately. We could use the actual bytes read to figure
1332 * out where to start, but we don't bother.
1333 */
1334 if (count > 1) {
1335 p = (const char *) data;
1336 for (i=0; i < count; i++, p += channel->block_size, block++) {
1337 error = io_channel_write_blk(channel, block,
1338 1, p);
1339 if (error)
1340 return error;
1341 }
1342 return 0;
1343 }
1344
1345 if (operation)
1346 printf(_("Error writing block %lu (%s) while %s. "), block,
1347 error_message(error), operation);
1348 else
1349 printf(_("Error writing block %lu (%s). "), block,
1350 error_message(error));
1351 preenhalt(ctx);
1352 if (ask(ctx, _("Ignore error"), 1))
1353 return 0;
1354
1355 return error;
1356}
1357
1358static const char *ehandler_operation(const char *op)
1359{
1360 const char *ret = operation;
1361
1362 operation = op;
1363 return ret;
1364}
1365
1366static void ehandler_init(io_channel channel)
1367{
1368 channel->read_error = e2fsck_handle_read_error;
1369 channel->write_error = e2fsck_handle_write_error;
1370}
1371
1372/*
1373 * journal.c --- code for handling the "ext3" journal
1374 *
1375 * Copyright (C) 2000 Andreas Dilger
1376 * Copyright (C) 2000 Theodore Ts'o
1377 *
1378 * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
1379 * Copyright (C) 1999 Red Hat Software
1380 *
1381 * This file may be redistributed under the terms of the
1382 * GNU General Public License version 2 or at your discretion
1383 * any later version.
1384 */
1385
1386/*
1387 * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
1388 * This creates a larger static binary, and a smaller binary using
1389 * shared libraries. It's also probably slightly less CPU-efficient,
1390 * which is why it's not on by default. But, it's a good way of
1391 * testing the functions in inode_io.c and fileio.c.
1392 */
1393#undef USE_INODE_IO
1394
1395/* Kernel compatibility functions for handling the journal. These allow us
1396 * to use the recovery.c file virtually unchanged from the kernel, so we
1397 * don't have to do much to keep kernel and user recovery in sync.
1398 */
1399static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
1400{
1401#ifdef USE_INODE_IO
1402 *phys = block;
1403 return 0;
1404#else
1405 struct inode *inode = journal->j_inode;
1406 errcode_t retval;
1407 blk_t pblk;
1408
1409 if (!inode) {
1410 *phys = block;
1411 return 0;
1412 }
1413
1414 retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
1415 &inode->i_ext2, NULL, 0, block, &pblk);
1416 *phys = pblk;
1417 return retval;
1418#endif
1419}
1420
1421static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
1422{
1423 struct buffer_head *bh;
1424
1425 bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
1426 if (!bh)
1427 return NULL;
1428
1429 bh->b_ctx = kdev->k_ctx;
1430 if (kdev->k_dev == K_DEV_FS)
1431 bh->b_io = kdev->k_ctx->fs->io;
1432 else
1433 bh->b_io = kdev->k_ctx->journal_io;
1434 bh->b_size = blocksize;
1435 bh->b_blocknr = blocknr;
1436
1437 return bh;
1438}
1439
1440static void sync_blockdev(kdev_t kdev)
1441{
1442 io_channel io;
1443
1444 if (kdev->k_dev == K_DEV_FS)
1445 io = kdev->k_ctx->fs->io;
1446 else
1447 io = kdev->k_ctx->journal_io;
1448
1449 io_channel_flush(io);
1450}
1451
1452static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
1453{
1454 int retval;
1455 struct buffer_head *bh;
1456
1457 for (; nr > 0; --nr) {
1458 bh = *bhp++;
1459 if (rw == READ && !bh->b_uptodate) {
1460 retval = io_channel_read_blk(bh->b_io,
1461 bh->b_blocknr,
1462 1, bh->b_data);
1463 if (retval) {
1464 bb_error_msg("while reading block %lu",
1465 (unsigned long) bh->b_blocknr);
1466 bh->b_err = retval;
1467 continue;
1468 }
1469 bh->b_uptodate = 1;
1470 } else if (rw == WRITE && bh->b_dirty) {
1471 retval = io_channel_write_blk(bh->b_io,
1472 bh->b_blocknr,
1473 1, bh->b_data);
1474 if (retval) {
1475 bb_error_msg("while writing block %lu",
1476 (unsigned long) bh->b_blocknr);
1477 bh->b_err = retval;
1478 continue;
1479 }
1480 bh->b_dirty = 0;
1481 bh->b_uptodate = 1;
1482 }
1483 }
1484}
1485
1486static void mark_buffer_dirty(struct buffer_head *bh)
1487{
1488 bh->b_dirty = 1;
1489}
1490
1491static inline void mark_buffer_clean(struct buffer_head * bh)
1492{
1493 bh->b_dirty = 0;
1494}
1495
1496static void brelse(struct buffer_head *bh)
1497{
1498 if (bh->b_dirty)
1499 ll_rw_block(WRITE, 1, &bh);
1500 ext2fs_free_mem(&bh);
1501}
1502
1503static int buffer_uptodate(struct buffer_head *bh)
1504{
1505 return bh->b_uptodate;
1506}
1507
1508static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
1509{
1510 bh->b_uptodate = val;
1511}
1512
1513static void wait_on_buffer(struct buffer_head *bh)
1514{
1515 if (!bh->b_uptodate)
1516 ll_rw_block(READ, 1, &bh);
1517}
1518
1519
1520static void e2fsck_clear_recover(e2fsck_t ctx, int error)
1521{
1522 ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
1523
1524 /* if we had an error doing journal recovery, we need a full fsck */
1525 if (error)
1526 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
1527 ext2fs_mark_super_dirty(ctx->fs);
1528}
1529
1530static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
1531{
1532 struct ext2_super_block *sb = ctx->fs->super;
1533 struct ext2_super_block jsuper;
1534 struct problem_context pctx;
1535 struct buffer_head *bh;
1536 struct inode *j_inode = NULL;
1537 struct kdev_s *dev_fs = NULL, *dev_journal;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +01001538 const char *journal_name = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00001539 journal_t *journal = NULL;
1540 errcode_t retval = 0;
1541 io_manager io_ptr = 0;
1542 unsigned long start = 0;
1543 blk_t blk;
1544 int ext_journal = 0;
1545 int tried_backup_jnl = 0;
1546 int i;
1547
1548 clear_problem_context(&pctx);
1549
1550 journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
1551 if (!journal) {
1552 return EXT2_ET_NO_MEMORY;
1553 }
1554
1555 dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
1556 if (!dev_fs) {
1557 retval = EXT2_ET_NO_MEMORY;
1558 goto errout;
1559 }
1560 dev_journal = dev_fs+1;
1561
1562 dev_fs->k_ctx = dev_journal->k_ctx = ctx;
1563 dev_fs->k_dev = K_DEV_FS;
1564 dev_journal->k_dev = K_DEV_JOURNAL;
1565
1566 journal->j_dev = dev_journal;
1567 journal->j_fs_dev = dev_fs;
1568 journal->j_inode = NULL;
1569 journal->j_blocksize = ctx->fs->blocksize;
1570
1571 if (uuid_is_null(sb->s_journal_uuid)) {
1572 if (!sb->s_journal_inum)
1573 return EXT2_ET_BAD_INODE_NUM;
1574 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
1575 "journal inode");
1576 if (!j_inode) {
1577 retval = EXT2_ET_NO_MEMORY;
1578 goto errout;
1579 }
1580
1581 j_inode->i_ctx = ctx;
1582 j_inode->i_ino = sb->s_journal_inum;
1583
1584 if ((retval = ext2fs_read_inode(ctx->fs,
1585 sb->s_journal_inum,
1586 &j_inode->i_ext2))) {
1587 try_backup_journal:
1588 if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
1589 tried_backup_jnl)
1590 goto errout;
1591 memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
1592 memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
1593 EXT2_N_BLOCKS*4);
1594 j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
1595 j_inode->i_ext2.i_links_count = 1;
1596 j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
1597 tried_backup_jnl++;
1598 }
1599 if (!j_inode->i_ext2.i_links_count ||
1600 !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
1601 retval = EXT2_ET_NO_JOURNAL;
1602 goto try_backup_journal;
1603 }
1604 if (j_inode->i_ext2.i_size / journal->j_blocksize <
1605 JFS_MIN_JOURNAL_BLOCKS) {
1606 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1607 goto try_backup_journal;
1608 }
1609 for (i=0; i < EXT2_N_BLOCKS; i++) {
1610 blk = j_inode->i_ext2.i_block[i];
1611 if (!blk) {
1612 if (i < EXT2_NDIR_BLOCKS) {
1613 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1614 goto try_backup_journal;
1615 }
1616 continue;
1617 }
1618 if (blk < sb->s_first_data_block ||
1619 blk >= sb->s_blocks_count) {
1620 retval = EXT2_ET_BAD_BLOCK_NUM;
1621 goto try_backup_journal;
1622 }
1623 }
1624 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
1625
1626#ifdef USE_INODE_IO
1627 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
1628 &j_inode->i_ext2,
1629 &journal_name);
1630 if (retval)
1631 goto errout;
1632
1633 io_ptr = inode_io_manager;
1634#else
1635 journal->j_inode = j_inode;
1636 ctx->journal_io = ctx->fs->io;
1637 if ((retval = journal_bmap(journal, 0, &start)) != 0)
1638 goto errout;
1639#endif
1640 } else {
1641 ext_journal = 1;
1642 if (!ctx->journal_name) {
1643 char uuid[37];
1644
1645 uuid_unparse(sb->s_journal_uuid, uuid);
1646 ctx->journal_name = blkid_get_devname(ctx->blkid,
1647 "UUID", uuid);
1648 if (!ctx->journal_name)
1649 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
1650 }
1651 journal_name = ctx->journal_name;
1652
1653 if (!journal_name) {
1654 fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
1655 return EXT2_ET_LOAD_EXT_JOURNAL;
1656 }
1657
1658 io_ptr = unix_io_manager;
1659 }
1660
1661#ifndef USE_INODE_IO
1662 if (ext_journal)
1663#endif
1664 retval = io_ptr->open(journal_name, IO_FLAG_RW,
1665 &ctx->journal_io);
1666 if (retval)
1667 goto errout;
1668
1669 io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
1670
1671 if (ext_journal) {
1672 if (ctx->fs->blocksize == 1024)
1673 start = 1;
1674 bh = getblk(dev_journal, start, ctx->fs->blocksize);
1675 if (!bh) {
1676 retval = EXT2_ET_NO_MEMORY;
1677 goto errout;
1678 }
1679 ll_rw_block(READ, 1, &bh);
1680 if ((retval = bh->b_err) != 0)
1681 goto errout;
1682 memcpy(&jsuper, start ? bh->b_data : bh->b_data + 1024,
1683 sizeof(jsuper));
1684 brelse(bh);
1685#if BB_BIG_ENDIAN
1686 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
1687 ext2fs_swap_super(&jsuper);
1688#endif
1689 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
1690 !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
1691 fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
1692 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1693 goto errout;
1694 }
1695 /* Make sure the journal UUID is correct */
1696 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
1697 sizeof(jsuper.s_uuid))) {
1698 fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
1699 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1700 goto errout;
1701 }
1702
1703 journal->j_maxlen = jsuper.s_blocks_count;
1704 start++;
1705 }
1706
1707 if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
1708 retval = EXT2_ET_NO_MEMORY;
1709 goto errout;
1710 }
1711
1712 journal->j_sb_buffer = bh;
1713 journal->j_superblock = (journal_superblock_t *)bh->b_data;
1714
1715#ifdef USE_INODE_IO
1716 ext2fs_free_mem(&j_inode);
1717#endif
1718
1719 *ret_journal = journal;
1720 return 0;
1721
1722errout:
1723 ext2fs_free_mem(&dev_fs);
1724 ext2fs_free_mem(&j_inode);
1725 ext2fs_free_mem(&journal);
1726 return retval;
1727
1728}
1729
1730static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
1731 struct problem_context *pctx)
1732{
1733 struct ext2_super_block *sb = ctx->fs->super;
1734 int recover = ctx->fs->super->s_feature_incompat &
1735 EXT3_FEATURE_INCOMPAT_RECOVER;
1736 int has_journal = ctx->fs->super->s_feature_compat &
1737 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1738
1739 if (has_journal || sb->s_journal_inum) {
1740 /* The journal inode is bogus, remove and force full fsck */
1741 pctx->ino = sb->s_journal_inum;
1742 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
1743 if (has_journal && sb->s_journal_inum)
1744 printf("*** ext3 journal has been deleted - "
1745 "filesystem is now ext2 only ***\n\n");
1746 sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1747 sb->s_journal_inum = 0;
1748 ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
1749 e2fsck_clear_recover(ctx, 1);
1750 return 0;
1751 }
1752 return EXT2_ET_BAD_INODE_NUM;
1753 } else if (recover) {
1754 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
1755 e2fsck_clear_recover(ctx, 1);
1756 return 0;
1757 }
1758 return EXT2_ET_UNSUPP_FEATURE;
1759 }
1760 return 0;
1761}
1762
1763#define V1_SB_SIZE 0x0024
1764static void clear_v2_journal_fields(journal_t *journal)
1765{
1766 e2fsck_t ctx = journal->j_dev->k_ctx;
1767 struct problem_context pctx;
1768
1769 clear_problem_context(&pctx);
1770
1771 if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
1772 return;
1773
1774 memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
1775 ctx->fs->blocksize-V1_SB_SIZE);
1776 mark_buffer_dirty(journal->j_sb_buffer);
1777}
1778
1779
1780static errcode_t e2fsck_journal_load(journal_t *journal)
1781{
1782 e2fsck_t ctx = journal->j_dev->k_ctx;
1783 journal_superblock_t *jsb;
1784 struct buffer_head *jbh = journal->j_sb_buffer;
1785 struct problem_context pctx;
1786
1787 clear_problem_context(&pctx);
1788
1789 ll_rw_block(READ, 1, &jbh);
1790 if (jbh->b_err) {
1791 bb_error_msg(_("reading journal superblock"));
1792 return jbh->b_err;
1793 }
1794
1795 jsb = journal->j_superblock;
1796 /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
1797 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
1798 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1799
1800 switch (ntohl(jsb->s_header.h_blocktype)) {
1801 case JFS_SUPERBLOCK_V1:
1802 journal->j_format_version = 1;
1803 if (jsb->s_feature_compat ||
1804 jsb->s_feature_incompat ||
1805 jsb->s_feature_ro_compat ||
1806 jsb->s_nr_users)
1807 clear_v2_journal_fields(journal);
1808 break;
1809
1810 case JFS_SUPERBLOCK_V2:
1811 journal->j_format_version = 2;
1812 if (ntohl(jsb->s_nr_users) > 1 &&
1813 uuid_is_null(ctx->fs->super->s_journal_uuid))
1814 clear_v2_journal_fields(journal);
1815 if (ntohl(jsb->s_nr_users) > 1) {
1816 fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
1817 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1818 }
1819 break;
1820
1821 /*
1822 * These should never appear in a journal super block, so if
1823 * they do, the journal is badly corrupted.
1824 */
1825 case JFS_DESCRIPTOR_BLOCK:
1826 case JFS_COMMIT_BLOCK:
1827 case JFS_REVOKE_BLOCK:
1828 return EXT2_ET_CORRUPT_SUPERBLOCK;
1829
1830 /* If we don't understand the superblock major type, but there
1831 * is a magic number, then it is likely to be a new format we
1832 * just don't understand, so leave it alone. */
1833 default:
1834 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1835 }
1836
1837 if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
1838 return EXT2_ET_UNSUPP_FEATURE;
1839
1840 if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
1841 return EXT2_ET_RO_UNSUPP_FEATURE;
1842
1843 /* We have now checked whether we know enough about the journal
1844 * format to be able to proceed safely, so any other checks that
1845 * fail we should attempt to recover from. */
1846 if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
1847 bb_error_msg(_("%s: no valid journal superblock found"),
1848 ctx->device_name);
1849 return EXT2_ET_CORRUPT_SUPERBLOCK;
1850 }
1851
1852 if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
1853 journal->j_maxlen = ntohl(jsb->s_maxlen);
1854 else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
1855 bb_error_msg(_("%s: journal too short"),
1856 ctx->device_name);
1857 return EXT2_ET_CORRUPT_SUPERBLOCK;
1858 }
1859
1860 journal->j_tail_sequence = ntohl(jsb->s_sequence);
1861 journal->j_transaction_sequence = journal->j_tail_sequence;
1862 journal->j_tail = ntohl(jsb->s_start);
1863 journal->j_first = ntohl(jsb->s_first);
1864 journal->j_last = ntohl(jsb->s_maxlen);
1865
1866 return 0;
1867}
1868
1869static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
1870 journal_t *journal)
1871{
1872 char *p;
1873 union {
1874 uuid_t uuid;
1875 __u32 val[4];
1876 } u;
1877 __u32 new_seq = 0;
1878 int i;
1879
1880 /* Leave a valid existing V1 superblock signature alone.
Denys Vlasenkob22bbff2009-07-04 16:50:43 +02001881 * Anything unrecognizable we overwrite with a new V2
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00001882 * signature. */
1883
1884 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
1885 jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
1886 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
1887 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
1888 }
1889
1890 /* Zero out everything else beyond the superblock header */
1891
1892 p = ((char *) jsb) + sizeof(journal_header_t);
1893 memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
1894
1895 jsb->s_blocksize = htonl(ctx->fs->blocksize);
1896 jsb->s_maxlen = htonl(journal->j_maxlen);
1897 jsb->s_first = htonl(1);
1898
1899 /* Initialize the journal sequence number so that there is "no"
1900 * chance we will find old "valid" transactions in the journal.
1901 * This avoids the need to zero the whole journal (slow to do,
1902 * and risky when we are just recovering the filesystem).
1903 */
1904 uuid_generate(u.uuid);
1905 for (i = 0; i < 4; i ++)
1906 new_seq ^= u.val[i];
1907 jsb->s_sequence = htonl(new_seq);
1908
1909 mark_buffer_dirty(journal->j_sb_buffer);
1910 ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
1911}
1912
1913static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
1914 journal_t *journal,
1915 struct problem_context *pctx)
1916{
1917 struct ext2_super_block *sb = ctx->fs->super;
1918 int recover = ctx->fs->super->s_feature_incompat &
1919 EXT3_FEATURE_INCOMPAT_RECOVER;
1920
1921 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1922 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
1923 e2fsck_journal_reset_super(ctx, journal->j_superblock,
1924 journal);
1925 journal->j_transaction_sequence = 1;
1926 e2fsck_clear_recover(ctx, recover);
1927 return 0;
1928 }
1929 return EXT2_ET_CORRUPT_SUPERBLOCK;
1930 } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
1931 return EXT2_ET_CORRUPT_SUPERBLOCK;
1932
1933 return 0;
1934}
1935
1936static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
1937 int reset, int drop)
1938{
1939 journal_superblock_t *jsb;
1940
1941 if (drop)
1942 mark_buffer_clean(journal->j_sb_buffer);
1943 else if (!(ctx->options & E2F_OPT_READONLY)) {
1944 jsb = journal->j_superblock;
1945 jsb->s_sequence = htonl(journal->j_transaction_sequence);
1946 if (reset)
1947 jsb->s_start = 0; /* this marks the journal as empty */
1948 mark_buffer_dirty(journal->j_sb_buffer);
1949 }
1950 brelse(journal->j_sb_buffer);
1951
1952 if (ctx->journal_io) {
1953 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1954 io_channel_close(ctx->journal_io);
1955 ctx->journal_io = 0;
1956 }
1957
1958#ifndef USE_INODE_IO
1959 ext2fs_free_mem(&journal->j_inode);
1960#endif
1961 ext2fs_free_mem(&journal->j_fs_dev);
1962 ext2fs_free_mem(&journal);
1963}
1964
1965/*
1966 * This function makes sure that the superblock fields regarding the
1967 * journal are consistent.
1968 */
1969static int e2fsck_check_ext3_journal(e2fsck_t ctx)
1970{
1971 struct ext2_super_block *sb = ctx->fs->super;
1972 journal_t *journal;
1973 int recover = ctx->fs->super->s_feature_incompat &
1974 EXT3_FEATURE_INCOMPAT_RECOVER;
1975 struct problem_context pctx;
1976 problem_t problem;
1977 int reset = 0, force_fsck = 0;
1978 int retval;
1979
1980 /* If we don't have any journal features, don't do anything more */
1981 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
1982 !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
1983 uuid_is_null(sb->s_journal_uuid))
1984 return 0;
1985
1986 clear_problem_context(&pctx);
1987 pctx.num = sb->s_journal_inum;
1988
1989 retval = e2fsck_get_journal(ctx, &journal);
1990 if (retval) {
1991 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
1992 (retval == EXT2_ET_BAD_BLOCK_NUM) ||
1993 (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
1994 (retval == EXT2_ET_NO_JOURNAL))
1995 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1996 return retval;
1997 }
1998
1999 retval = e2fsck_journal_load(journal);
2000 if (retval) {
2001 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
2002 ((retval == EXT2_ET_UNSUPP_FEATURE) &&
2003 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
2004 &pctx))) ||
2005 ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
2006 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
2007 &pctx))) ||
2008 ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
2009 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
2010 retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
2011 &pctx);
2012 e2fsck_journal_release(ctx, journal, 0, 1);
2013 return retval;
2014 }
2015
2016 /*
2017 * We want to make the flags consistent here. We will not leave with
2018 * needs_recovery set but has_journal clear. We can't get in a loop
2019 * with -y, -n, or -p, only if a user isn't making up their mind.
2020 */
2021no_has_journal:
2022 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
2023 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
2024 pctx.str = "inode";
2025 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
2026 if (recover &&
2027 !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
2028 goto no_has_journal;
2029 /*
2030 * Need a full fsck if we are releasing a
2031 * journal stored on a reserved inode.
2032 */
2033 force_fsck = recover ||
2034 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
2035 /* Clear all of the journal fields */
2036 sb->s_journal_inum = 0;
2037 sb->s_journal_dev = 0;
2038 memset(sb->s_journal_uuid, 0,
2039 sizeof(sb->s_journal_uuid));
2040 e2fsck_clear_recover(ctx, force_fsck);
2041 } else if (!(ctx->options & E2F_OPT_READONLY)) {
2042 sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2043 ext2fs_mark_super_dirty(ctx->fs);
2044 }
2045 }
2046
2047 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
2048 !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
2049 journal->j_superblock->s_start != 0) {
2050 /* Print status information */
2051 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
2052 if (ctx->superblock)
2053 problem = PR_0_JOURNAL_RUN_DEFAULT;
2054 else
2055 problem = PR_0_JOURNAL_RUN;
2056 if (fix_problem(ctx, problem, &pctx)) {
2057 ctx->options |= E2F_OPT_FORCE;
2058 sb->s_feature_incompat |=
2059 EXT3_FEATURE_INCOMPAT_RECOVER;
2060 ext2fs_mark_super_dirty(ctx->fs);
2061 } else if (fix_problem(ctx,
2062 PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
2063 reset = 1;
2064 sb->s_state &= ~EXT2_VALID_FS;
2065 ext2fs_mark_super_dirty(ctx->fs);
2066 }
2067 /*
2068 * If the user answers no to the above question, we
2069 * ignore the fact that journal apparently has data;
2070 * accidentally replaying over valid data would be far
2071 * worse than skipping a questionable recovery.
2072 *
2073 * XXX should we abort with a fatal error here? What
2074 * will the ext3 kernel code do if a filesystem with
2075 * !NEEDS_RECOVERY but with a non-zero
2076 * journal->j_superblock->s_start is mounted?
2077 */
2078 }
2079
2080 e2fsck_journal_release(ctx, journal, reset, 0);
2081 return retval;
2082}
2083
2084static errcode_t recover_ext3_journal(e2fsck_t ctx)
2085{
2086 journal_t *journal;
2087 int retval;
2088
2089 journal_init_revoke_caches();
2090 retval = e2fsck_get_journal(ctx, &journal);
2091 if (retval)
2092 return retval;
2093
2094 retval = e2fsck_journal_load(journal);
2095 if (retval)
2096 goto errout;
2097
2098 retval = journal_init_revoke(journal, 1024);
2099 if (retval)
2100 goto errout;
2101
2102 retval = -journal_recover(journal);
2103 if (retval)
2104 goto errout;
2105
2106 if (journal->j_superblock->s_errno) {
2107 ctx->fs->super->s_state |= EXT2_ERROR_FS;
2108 ext2fs_mark_super_dirty(ctx->fs);
2109 journal->j_superblock->s_errno = 0;
2110 mark_buffer_dirty(journal->j_sb_buffer);
2111 }
2112
2113errout:
2114 journal_destroy_revoke(journal);
2115 journal_destroy_revoke_caches();
2116 e2fsck_journal_release(ctx, journal, 1, 0);
2117 return retval;
2118}
2119
2120static int e2fsck_run_ext3_journal(e2fsck_t ctx)
2121{
2122 io_manager io_ptr = ctx->fs->io->manager;
2123 int blocksize = ctx->fs->blocksize;
2124 errcode_t retval, recover_retval;
2125
2126 printf(_("%s: recovering journal\n"), ctx->device_name);
2127 if (ctx->options & E2F_OPT_READONLY) {
2128 printf(_("%s: won't do journal recovery while read-only\n"),
2129 ctx->device_name);
2130 return EXT2_ET_FILE_RO;
2131 }
2132
2133 if (ctx->fs->flags & EXT2_FLAG_DIRTY)
2134 ext2fs_flush(ctx->fs); /* Force out any modifications */
2135
2136 recover_retval = recover_ext3_journal(ctx);
2137
2138 /*
2139 * Reload the filesystem context to get up-to-date data from disk
2140 * because journal recovery will change the filesystem under us.
2141 */
2142 ext2fs_close(ctx->fs);
2143 retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
2144 ctx->superblock, blocksize, io_ptr,
2145 &ctx->fs);
2146
2147 if (retval) {
2148 bb_error_msg(_("while trying to re-open %s"),
2149 ctx->device_name);
2150 bb_error_msg_and_die(0);
2151 }
2152 ctx->fs->priv_data = ctx;
2153
2154 /* Set the superblock flags */
2155 e2fsck_clear_recover(ctx, recover_retval);
2156 return recover_retval;
2157}
2158
2159/*
2160 * This function will move the journal inode from a visible file in
2161 * the filesystem directory hierarchy to the reserved inode if necessary.
2162 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002163static const char *const journal_names[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002164 ".journal", "journal", ".journal.dat", "journal.dat", 0 };
2165
2166static void e2fsck_move_ext3_journal(e2fsck_t ctx)
2167{
2168 struct ext2_super_block *sb = ctx->fs->super;
2169 struct problem_context pctx;
2170 struct ext2_inode inode;
2171 ext2_filsys fs = ctx->fs;
2172 ext2_ino_t ino;
2173 errcode_t retval;
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002174 const char *const * cpp;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002175 int group, mount_flags;
2176
2177 clear_problem_context(&pctx);
2178
2179 /*
2180 * If the filesystem is opened read-only, or there is no
2181 * journal, then do nothing.
2182 */
2183 if ((ctx->options & E2F_OPT_READONLY) ||
2184 (sb->s_journal_inum == 0) ||
2185 !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2186 return;
2187
2188 /*
2189 * Read in the journal inode
2190 */
2191 if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
2192 return;
2193
2194 /*
2195 * If it's necessary to backup the journal inode, do so.
2196 */
2197 if ((sb->s_jnl_backup_type == 0) ||
2198 ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
2199 memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
2200 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
2201 memcpy(sb->s_jnl_blocks, inode.i_block,
2202 EXT2_N_BLOCKS*4);
2203 sb->s_jnl_blocks[16] = inode.i_size;
2204 sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2205 ext2fs_mark_super_dirty(fs);
2206 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2207 }
2208 }
2209
2210 /*
2211 * If the journal is already the hidden inode, then do nothing
2212 */
2213 if (sb->s_journal_inum == EXT2_JOURNAL_INO)
2214 return;
2215
2216 /*
2217 * The journal inode had better have only one link and not be readable.
2218 */
2219 if (inode.i_links_count != 1)
2220 return;
2221
2222 /*
2223 * If the filesystem is mounted, or we can't tell whether
2224 * or not it's mounted, do nothing.
2225 */
2226 retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
2227 if (retval || (mount_flags & EXT2_MF_MOUNTED))
2228 return;
2229
2230 /*
2231 * If we can't find the name of the journal inode, then do
2232 * nothing.
2233 */
2234 for (cpp = journal_names; *cpp; cpp++) {
2235 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
2236 strlen(*cpp), 0, &ino);
2237 if ((retval == 0) && (ino == sb->s_journal_inum))
2238 break;
2239 }
2240 if (*cpp == 0)
2241 return;
2242
2243 /* We need the inode bitmap to be loaded */
2244 retval = ext2fs_read_bitmaps(fs);
2245 if (retval)
2246 return;
2247
2248 pctx.str = *cpp;
2249 if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
2250 return;
2251
2252 /*
2253 * OK, we've done all the checks, let's actually move the
2254 * journal inode. Errors at this point mean we need to force
2255 * an ext2 filesystem check.
2256 */
2257 if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
2258 goto err_out;
2259 if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
2260 goto err_out;
2261 sb->s_journal_inum = EXT2_JOURNAL_INO;
2262 ext2fs_mark_super_dirty(fs);
2263 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2264 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00002265 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002266 if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
2267 goto err_out;
2268
2269 group = ext2fs_group_of_ino(fs, ino);
2270 ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
2271 ext2fs_mark_ib_dirty(fs);
2272 fs->group_desc[group].bg_free_inodes_count++;
2273 fs->super->s_free_inodes_count++;
2274 return;
2275
2276err_out:
2277 pctx.errcode = retval;
2278 fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
2279 fs->super->s_state &= ~EXT2_VALID_FS;
2280 ext2fs_mark_super_dirty(fs);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002281}
2282
2283/*
2284 * message.c --- print e2fsck messages (with compression)
2285 *
2286 * print_e2fsck_message() prints a message to the user, using
2287 * compression techniques and expansions of abbreviations.
2288 *
2289 * The following % expansions are supported:
2290 *
2291 * %b <blk> block number
2292 * %B <blkcount> integer
2293 * %c <blk2> block number
2294 * %Di <dirent>->ino inode number
2295 * %Dn <dirent>->name string
2296 * %Dr <dirent>->rec_len
2297 * %Dl <dirent>->name_len
2298 * %Dt <dirent>->filetype
2299 * %d <dir> inode number
2300 * %g <group> integer
2301 * %i <ino> inode number
2302 * %Is <inode> -> i_size
2303 * %IS <inode> -> i_extra_isize
2304 * %Ib <inode> -> i_blocks
2305 * %Il <inode> -> i_links_count
2306 * %Im <inode> -> i_mode
2307 * %IM <inode> -> i_mtime
2308 * %IF <inode> -> i_faddr
2309 * %If <inode> -> i_file_acl
2310 * %Id <inode> -> i_dir_acl
2311 * %Iu <inode> -> i_uid
2312 * %Ig <inode> -> i_gid
2313 * %j <ino2> inode number
2314 * %m <com_err error message>
2315 * %N <num>
2316 * %p ext2fs_get_pathname of directory <ino>
2317 * %P ext2fs_get_pathname of <dirent>->ino with <ino2> as
2318 * the containing directory. (If dirent is NULL
2319 * then return the pathname of directory <ino2>)
2320 * %q ext2fs_get_pathname of directory <dir>
2321 * %Q ext2fs_get_pathname of directory <ino> with <dir> as
2322 * the containing directory.
2323 * %s <str> miscellaneous string
2324 * %S backup superblock
2325 * %X <num> hexadecimal format
2326 *
2327 * The following '@' expansions are supported:
2328 *
2329 * @a extended attribute
2330 * @A error allocating
2331 * @b block
2332 * @B bitmap
2333 * @c compress
2334 * @C conflicts with some other fs block
2335 * @D deleted
2336 * @d directory
2337 * @e entry
2338 * @E Entry '%Dn' in %p (%i)
2339 * @f filesystem
2340 * @F for @i %i (%Q) is
2341 * @g group
2342 * @h HTREE directory inode
2343 * @i inode
2344 * @I illegal
2345 * @j journal
2346 * @l lost+found
2347 * @L is a link
2348 * @m multiply-claimed
2349 * @n invalid
2350 * @o orphaned
2351 * @p problem in
2352 * @r root inode
2353 * @s should be
2354 * @S superblock
2355 * @u unattached
2356 * @v device
2357 * @z zero-length
2358 */
2359
2360
2361/*
2362 * This structure defines the abbreviations used by the text strings
2363 * below. The first character in the string is the index letter. An
2364 * abbreviation of the form '@<i>' is expanded by looking up the index
2365 * letter <i> in the table below.
2366 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002367static const char *const abbrevs[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002368 N_("aextended attribute"),
2369 N_("Aerror allocating"),
2370 N_("bblock"),
2371 N_("Bbitmap"),
2372 N_("ccompress"),
2373 N_("Cconflicts with some other fs @b"),
2374 N_("iinode"),
2375 N_("Iillegal"),
2376 N_("jjournal"),
2377 N_("Ddeleted"),
2378 N_("ddirectory"),
2379 N_("eentry"),
2380 N_("E@e '%Dn' in %p (%i)"),
2381 N_("ffilesystem"),
2382 N_("Ffor @i %i (%Q) is"),
2383 N_("ggroup"),
2384 N_("hHTREE @d @i"),
2385 N_("llost+found"),
2386 N_("Lis a link"),
Denys Vlasenkoef3817c2010-01-08 09:07:25 +01002387 N_("mmultiply-claimed"),
2388 N_("ninvalid"),
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002389 N_("oorphaned"),
2390 N_("pproblem in"),
2391 N_("rroot @i"),
2392 N_("sshould be"),
2393 N_("Ssuper@b"),
2394 N_("uunattached"),
2395 N_("vdevice"),
2396 N_("zzero-length"),
2397 "@@",
2398 0
2399 };
2400
2401/*
2402 * Give more user friendly names to the "special" inodes.
2403 */
2404#define num_special_inodes 11
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002405static const char *const special_inode_name[] =
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002406{
2407 N_("<The NULL inode>"), /* 0 */
2408 N_("<The bad blocks inode>"), /* 1 */
2409 "/", /* 2 */
2410 N_("<The ACL index inode>"), /* 3 */
2411 N_("<The ACL data inode>"), /* 4 */
2412 N_("<The boot loader inode>"), /* 5 */
2413 N_("<The undelete directory inode>"), /* 6 */
2414 N_("<The group descriptor inode>"), /* 7 */
2415 N_("<The journal inode>"), /* 8 */
2416 N_("<Reserved inode 9>"), /* 9 */
2417 N_("<Reserved inode 10>"), /* 10 */
2418};
2419
2420/*
2421 * This function does "safe" printing. It will convert non-printable
2422 * ASCII characters using '^' and M- notation.
2423 */
2424static void safe_print(const char *cp, int len)
2425{
2426 unsigned char ch;
2427
2428 if (len < 0)
2429 len = strlen(cp);
2430
2431 while (len--) {
2432 ch = *cp++;
2433 if (ch > 128) {
2434 fputs("M-", stdout);
2435 ch -= 128;
2436 }
2437 if ((ch < 32) || (ch == 0x7f)) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00002438 bb_putchar('^');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002439 ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
2440 }
Denis Vlasenko4daad902007-09-27 10:20:47 +00002441 bb_putchar(ch);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002442 }
2443}
2444
2445
2446/*
2447 * This function prints a pathname, using the ext2fs_get_pathname
2448 * function
2449 */
2450static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
2451{
2452 errcode_t retval;
2453 char *path;
2454
2455 if (!dir && (ino < num_special_inodes)) {
2456 fputs(_(special_inode_name[ino]), stdout);
2457 return;
2458 }
2459
2460 retval = ext2fs_get_pathname(fs, dir, ino, &path);
2461 if (retval)
2462 fputs("???", stdout);
2463 else {
2464 safe_print(path, -1);
2465 ext2fs_free_mem(&path);
2466 }
2467}
2468
2469static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2470 struct problem_context *pctx, int first);
2471/*
2472 * This function handles the '@' expansion. We allow recursive
2473 * expansion; an @ expression can contain further '@' and '%'
2474 * expressions.
2475 */
2476static void expand_at_expression(e2fsck_t ctx, char ch,
2477 struct problem_context *pctx,
2478 int *first)
2479{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002480 const char *const *cpp;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002481 const char *str;
2482
2483 /* Search for the abbreviation */
2484 for (cpp = abbrevs; *cpp; cpp++) {
2485 if (ch == *cpp[0])
2486 break;
2487 }
2488 if (*cpp) {
2489 str = _(*cpp) + 1;
2490 if (*first && islower(*str)) {
2491 *first = 0;
Denis Vlasenko4daad902007-09-27 10:20:47 +00002492 bb_putchar(toupper(*str++));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002493 }
2494 print_e2fsck_message(ctx, str, pctx, *first);
2495 } else
2496 printf("@%c", ch);
2497}
2498
2499/*
2500 * This function expands '%IX' expressions
2501 */
2502static void expand_inode_expression(char ch,
2503 struct problem_context *ctx)
2504{
2505 struct ext2_inode *inode;
2506 struct ext2_inode_large *large_inode;
2507 char * time_str;
2508 time_t t;
2509 int do_gmt = -1;
2510
2511 if (!ctx || !ctx->inode)
2512 goto no_inode;
2513
2514 inode = ctx->inode;
2515 large_inode = (struct ext2_inode_large *) inode;
2516
2517 switch (ch) {
2518 case 's':
2519 if (LINUX_S_ISDIR(inode->i_mode))
2520 printf("%u", inode->i_size);
2521 else {
2522 printf("%"PRIu64, (inode->i_size |
2523 ((uint64_t) inode->i_size_high << 32)));
2524 }
2525 break;
2526 case 'S':
2527 printf("%u", large_inode->i_extra_isize);
2528 break;
2529 case 'b':
2530 printf("%u", inode->i_blocks);
2531 break;
2532 case 'l':
2533 printf("%d", inode->i_links_count);
2534 break;
2535 case 'm':
2536 printf("0%o", inode->i_mode);
2537 break;
2538 case 'M':
2539 /* The diet libc doesn't respect the TZ environemnt variable */
2540 if (do_gmt == -1) {
2541 time_str = getenv("TZ");
2542 if (!time_str)
2543 time_str = "";
2544 do_gmt = !strcmp(time_str, "GMT");
2545 }
2546 t = inode->i_mtime;
2547 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
2548 printf("%.24s", time_str);
2549 break;
2550 case 'F':
2551 printf("%u", inode->i_faddr);
2552 break;
2553 case 'f':
2554 printf("%u", inode->i_file_acl);
2555 break;
2556 case 'd':
2557 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
2558 inode->i_dir_acl : 0));
2559 break;
2560 case 'u':
2561 printf("%d", (inode->i_uid |
2562 (inode->osd2.linux2.l_i_uid_high << 16)));
2563 break;
2564 case 'g':
2565 printf("%d", (inode->i_gid |
2566 (inode->osd2.linux2.l_i_gid_high << 16)));
2567 break;
2568 default:
2569 no_inode:
2570 printf("%%I%c", ch);
2571 break;
2572 }
2573}
2574
2575/*
2576 * This function expands '%dX' expressions
2577 */
2578static void expand_dirent_expression(char ch,
2579 struct problem_context *ctx)
2580{
2581 struct ext2_dir_entry *dirent;
2582 int len;
2583
2584 if (!ctx || !ctx->dirent)
2585 goto no_dirent;
2586
2587 dirent = ctx->dirent;
2588
2589 switch (ch) {
2590 case 'i':
2591 printf("%u", dirent->inode);
2592 break;
2593 case 'n':
2594 len = dirent->name_len & 0xFF;
2595 if (len > EXT2_NAME_LEN)
2596 len = EXT2_NAME_LEN;
2597 if (len > dirent->rec_len)
2598 len = dirent->rec_len;
2599 safe_print(dirent->name, len);
2600 break;
2601 case 'r':
2602 printf("%u", dirent->rec_len);
2603 break;
2604 case 'l':
2605 printf("%u", dirent->name_len & 0xFF);
2606 break;
2607 case 't':
2608 printf("%u", dirent->name_len >> 8);
2609 break;
2610 default:
2611 no_dirent:
2612 printf("%%D%c", ch);
2613 break;
2614 }
2615}
2616
2617static void expand_percent_expression(ext2_filsys fs, char ch,
2618 struct problem_context *ctx)
2619{
2620 if (!ctx)
2621 goto no_context;
2622
2623 switch (ch) {
2624 case '%':
Denis Vlasenko4daad902007-09-27 10:20:47 +00002625 bb_putchar('%');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002626 break;
2627 case 'b':
2628 printf("%u", ctx->blk);
2629 break;
2630 case 'B':
2631 printf("%"PRIi64, ctx->blkcount);
2632 break;
2633 case 'c':
2634 printf("%u", ctx->blk2);
2635 break;
2636 case 'd':
2637 printf("%u", ctx->dir);
2638 break;
2639 case 'g':
2640 printf("%d", ctx->group);
2641 break;
2642 case 'i':
2643 printf("%u", ctx->ino);
2644 break;
2645 case 'j':
2646 printf("%u", ctx->ino2);
2647 break;
2648 case 'm':
Denis Vlasenko605b20e2007-09-30 16:22:36 +00002649 fputs(error_message(ctx->errcode), stdout);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002650 break;
2651 case 'N':
2652 printf("%"PRIi64, ctx->num);
2653 break;
2654 case 'p':
2655 print_pathname(fs, ctx->ino, 0);
2656 break;
2657 case 'P':
2658 print_pathname(fs, ctx->ino2,
2659 ctx->dirent ? ctx->dirent->inode : 0);
2660 break;
2661 case 'q':
2662 print_pathname(fs, ctx->dir, 0);
2663 break;
2664 case 'Q':
2665 print_pathname(fs, ctx->dir, ctx->ino);
2666 break;
2667 case 'S':
2668 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
2669 break;
2670 case 's':
Denis Vlasenko605b20e2007-09-30 16:22:36 +00002671 fputs((ctx->str ? ctx->str : "NULL"), stdout);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002672 break;
2673 case 'X':
2674 printf("0x%"PRIi64, ctx->num);
2675 break;
2676 default:
2677 no_context:
2678 printf("%%%c", ch);
2679 break;
2680 }
2681}
2682
2683
2684static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2685 struct problem_context *pctx, int first)
2686{
2687 ext2_filsys fs = ctx->fs;
2688 const char * cp;
2689 int i;
2690
2691 e2fsck_clear_progbar(ctx);
2692 for (cp = msg; *cp; cp++) {
2693 if (cp[0] == '@') {
2694 cp++;
2695 expand_at_expression(ctx, *cp, pctx, &first);
2696 } else if (cp[0] == '%' && cp[1] == 'I') {
2697 cp += 2;
2698 expand_inode_expression(*cp, pctx);
2699 } else if (cp[0] == '%' && cp[1] == 'D') {
2700 cp += 2;
2701 expand_dirent_expression(*cp, pctx);
2702 } else if ((cp[0] == '%')) {
2703 cp++;
2704 expand_percent_expression(fs, *cp, pctx);
2705 } else {
2706 for (i=0; cp[i]; i++)
2707 if ((cp[i] == '@') || cp[i] == '%')
2708 break;
2709 printf("%.*s", i, cp);
2710 cp += i-1;
2711 }
2712 first = 0;
2713 }
2714}
2715
2716
2717/*
2718 * region.c --- code which manages allocations within a region.
2719 */
2720
2721struct region_el {
2722 region_addr_t start;
2723 region_addr_t end;
2724 struct region_el *next;
2725};
2726
2727struct region_struct {
2728 region_addr_t min;
2729 region_addr_t max;
2730 struct region_el *allocated;
2731};
2732
2733static region_t region_create(region_addr_t min, region_addr_t max)
2734{
2735 region_t region;
2736
Denys Vlasenkoef3817c2010-01-08 09:07:25 +01002737 region = xzalloc(sizeof(struct region_struct));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002738 region->min = min;
2739 region->max = max;
2740 return region;
2741}
2742
2743static void region_free(region_t region)
2744{
2745 struct region_el *r, *next;
2746
2747 for (r = region->allocated; r; r = next) {
2748 next = r->next;
2749 free(r);
2750 }
2751 memset(region, 0, sizeof(struct region_struct));
2752 free(region);
2753}
2754
2755static int region_allocate(region_t region, region_addr_t start, int n)
2756{
2757 struct region_el *r, *new_region, *prev, *next;
2758 region_addr_t end;
2759
2760 end = start+n;
2761 if ((start < region->min) || (end > region->max))
2762 return -1;
2763 if (n == 0)
2764 return 1;
2765
2766 /*
2767 * Search through the linked list. If we find that it
2768 * conflicts witih something that's already allocated, return
2769 * 1; if we can find an existing region which we can grow, do
2770 * so. Otherwise, stop when we find the appropriate place
2771 * insert a new region element into the linked list.
2772 */
2773 for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
2774 if (((start >= r->start) && (start < r->end)) ||
2775 ((end > r->start) && (end <= r->end)) ||
2776 ((start <= r->start) && (end >= r->end)))
2777 return 1;
2778 if (end == r->start) {
2779 r->start = start;
2780 return 0;
2781 }
2782 if (start == r->end) {
2783 if ((next = r->next)) {
2784 if (end > next->start)
2785 return 1;
2786 if (end == next->start) {
2787 r->end = next->end;
2788 r->next = next->next;
2789 free(next);
2790 return 0;
2791 }
2792 }
2793 r->end = end;
2794 return 0;
2795 }
2796 if (start < r->start)
2797 break;
2798 }
2799 /*
2800 * Insert a new region element structure into the linked list
2801 */
Denys Vlasenkoef3817c2010-01-08 09:07:25 +01002802 new_region = xmalloc(sizeof(struct region_el));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002803 new_region->start = start;
2804 new_region->end = start + n;
2805 new_region->next = r;
2806 if (prev)
2807 prev->next = new_region;
2808 else
2809 region->allocated = new_region;
2810 return 0;
2811}
2812
2813/*
2814 * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
2815 *
2816 * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
2817 * and applies the following tests to each inode:
2818 *
2819 * - The mode field of the inode must be legal.
2820 * - The size and block count fields of the inode are correct.
2821 * - A data block must not be used by another inode
2822 *
2823 * Pass 1 also gathers the collects the following information:
2824 *
2825 * - A bitmap of which inodes are in use. (inode_used_map)
2826 * - A bitmap of which inodes are directories. (inode_dir_map)
2827 * - A bitmap of which inodes are regular files. (inode_reg_map)
2828 * - A bitmap of which inodes have bad fields. (inode_bad_map)
2829 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
2830 * - A bitmap of which blocks are in use. (block_found_map)
2831 * - A bitmap of which blocks are in use by two inodes (block_dup_map)
2832 * - The data blocks of the directory inodes. (dir_map)
2833 *
2834 * Pass 1 is designed to stash away enough information so that the
2835 * other passes should not need to read in the inode information
2836 * during the normal course of a filesystem check. (Althogh if an
2837 * inconsistency is detected, other passes may need to read in an
2838 * inode to fix it.)
2839 *
2840 * Note that pass 1B will be invoked if there are any duplicate blocks
2841 * found.
2842 */
2843
2844
2845static int process_block(ext2_filsys fs, blk_t *blocknr,
2846 e2_blkcnt_t blockcnt, blk_t ref_blk,
2847 int ref_offset, void *priv_data);
2848static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
2849 e2_blkcnt_t blockcnt, blk_t ref_blk,
2850 int ref_offset, void *priv_data);
2851static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
2852 char *block_buf);
2853static void mark_table_blocks(e2fsck_t ctx);
2854static void alloc_imagic_map(e2fsck_t ctx);
2855static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
2856static void handle_fs_bad_blocks(e2fsck_t ctx);
2857static void process_inodes(e2fsck_t ctx, char *block_buf);
2858static int process_inode_cmp(const void *a, const void *b);
2859static errcode_t scan_callback(ext2_filsys fs,
2860 dgrp_t group, void * priv_data);
2861static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
2862 char *block_buf, int adjust_sign);
2863/* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
2864
2865static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
2866 struct ext2_inode * inode, int bufsize,
2867 const char *proc);
2868
2869struct process_block_struct_1 {
2870 ext2_ino_t ino;
2871 unsigned is_dir:1, is_reg:1, clear:1, suppress:1,
2872 fragmented:1, compressed:1, bbcheck:1;
2873 blk_t num_blocks;
2874 blk_t max_blocks;
2875 e2_blkcnt_t last_block;
2876 int num_illegal_blocks;
2877 blk_t previous_block;
2878 struct ext2_inode *inode;
2879 struct problem_context *pctx;
2880 ext2fs_block_bitmap fs_meta_blocks;
2881 e2fsck_t ctx;
2882};
2883
2884struct process_inode_block {
2885 ext2_ino_t ino;
2886 struct ext2_inode inode;
2887};
2888
2889struct scan_callback_struct {
2890 e2fsck_t ctx;
2891 char *block_buf;
2892};
2893
2894/*
2895 * For the inodes to process list.
2896 */
2897static struct process_inode_block *inodes_to_process;
2898static int process_inode_count;
2899
2900static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
2901 EXT2_MIN_BLOCK_LOG_SIZE + 1];
2902
2903/*
2904 * Free all memory allocated by pass1 in preparation for restarting
2905 * things.
2906 */
2907static void unwind_pass1(void)
2908{
2909 ext2fs_free_mem(&inodes_to_process);
2910}
2911
2912/*
2913 * Check to make sure a device inode is real. Returns 1 if the device
2914 * checks out, 0 if not.
2915 *
2916 * Note: this routine is now also used to check FIFO's and Sockets,
2917 * since they have the same requirement; the i_block fields should be
2918 * zero.
2919 */
2920static int
2921e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
2922{
2923 int i;
2924
2925 /*
2926 * If i_blocks is non-zero, or the index flag is set, then
2927 * this is a bogus device/fifo/socket
2928 */
2929 if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
2930 (inode->i_flags & EXT2_INDEX_FL))
2931 return 0;
2932
2933 /*
2934 * We should be able to do the test below all the time, but
2935 * because the kernel doesn't forcibly clear the device
2936 * inode's additional i_block fields, there are some rare
2937 * occasions when a legitimate device inode will have non-zero
2938 * additional i_block fields. So for now, we only complain
2939 * when the immutable flag is set, which should never happen
2940 * for devices. (And that's when the problem is caused, since
2941 * you can't set or clear immutable flags for devices.) Once
2942 * the kernel has been fixed we can change this...
2943 */
2944 if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
2945 for (i=4; i < EXT2_N_BLOCKS; i++)
2946 if (inode->i_block[i])
2947 return 0;
2948 }
2949 return 1;
2950}
2951
2952/*
2953 * Check to make sure a symlink inode is real. Returns 1 if the symlink
2954 * checks out, 0 if not.
2955 */
2956static int
2957e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
2958{
2959 unsigned int len;
2960 int i;
2961 blk_t blocks;
2962
2963 if ((inode->i_size_high || inode->i_size == 0) ||
2964 (inode->i_flags & EXT2_INDEX_FL))
2965 return 0;
2966
2967 blocks = ext2fs_inode_data_blocks(fs, inode);
2968 if (blocks) {
2969 if ((inode->i_size >= fs->blocksize) ||
2970 (blocks != fs->blocksize >> 9) ||
2971 (inode->i_block[0] < fs->super->s_first_data_block) ||
2972 (inode->i_block[0] >= fs->super->s_blocks_count))
2973 return 0;
2974
2975 for (i = 1; i < EXT2_N_BLOCKS; i++)
2976 if (inode->i_block[i])
2977 return 0;
2978
2979 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
2980 return 0;
2981
2982 len = strnlen(buf, fs->blocksize);
2983 if (len == fs->blocksize)
2984 return 0;
2985 } else {
2986 if (inode->i_size >= sizeof(inode->i_block))
2987 return 0;
2988
2989 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
2990 if (len == sizeof(inode->i_block))
2991 return 0;
2992 }
2993 if (len != inode->i_size)
2994 return 0;
2995 return 1;
2996}
2997
2998/*
2999 * If the immutable (or append-only) flag is set on the inode, offer
3000 * to clear it.
3001 */
3002#define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
3003static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
3004{
3005 if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
3006 return;
3007
3008 if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
3009 return;
3010
3011 pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
3012 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3013}
3014
3015/*
3016 * If device, fifo or socket, check size is zero -- if not offer to
3017 * clear it
3018 */
3019static void check_size(e2fsck_t ctx, struct problem_context *pctx)
3020{
3021 struct ext2_inode *inode = pctx->inode;
3022
3023 if ((inode->i_size == 0) && (inode->i_size_high == 0))
3024 return;
3025
3026 if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
3027 return;
3028
3029 inode->i_size = 0;
3030 inode->i_size_high = 0;
3031 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3032}
3033
3034static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
3035{
3036 struct ext2_super_block *sb = ctx->fs->super;
3037 struct ext2_inode_large *inode;
3038 struct ext2_ext_attr_entry *entry;
3039 char *start, *end;
3040 int storage_size, remain, offs;
3041 int problem = 0;
3042
3043 inode = (struct ext2_inode_large *) pctx->inode;
3044 storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
3045 inode->i_extra_isize;
3046 start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3047 inode->i_extra_isize + sizeof(__u32);
3048 end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
3049 entry = (struct ext2_ext_attr_entry *) start;
3050
3051 /* scan all entry's headers first */
3052
3053 /* take finish entry 0UL into account */
3054 remain = storage_size - sizeof(__u32);
3055 offs = end - start;
3056
3057 while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
3058
3059 /* header eats this space */
3060 remain -= sizeof(struct ext2_ext_attr_entry);
3061
3062 /* is attribute name valid? */
3063 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
3064 pctx->num = entry->e_name_len;
3065 problem = PR_1_ATTR_NAME_LEN;
3066 goto fix;
3067 }
3068
3069 /* attribute len eats this space */
3070 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
3071
3072 /* check value size */
3073 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
3074 pctx->num = entry->e_value_size;
3075 problem = PR_1_ATTR_VALUE_SIZE;
3076 goto fix;
3077 }
3078
3079 /* check value placement */
3080 if (entry->e_value_offs +
3081 EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
3082 printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
3083 pctx->num = entry->e_value_offs;
3084 problem = PR_1_ATTR_VALUE_OFFSET;
3085 goto fix;
3086 }
3087
3088 /* e_value_block must be 0 in inode's ea */
3089 if (entry->e_value_block != 0) {
3090 pctx->num = entry->e_value_block;
3091 problem = PR_1_ATTR_VALUE_BLOCK;
3092 goto fix;
3093 }
3094
3095 /* e_hash must be 0 in inode's ea */
3096 if (entry->e_hash != 0) {
3097 pctx->num = entry->e_hash;
3098 problem = PR_1_ATTR_HASH;
3099 goto fix;
3100 }
3101
3102 remain -= entry->e_value_size;
3103 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
3104
3105 entry = EXT2_EXT_ATTR_NEXT(entry);
3106 }
3107fix:
3108 /*
3109 * it seems like a corruption. it's very unlikely we could repair
3110 * EA(s) in automatic fashion -bzzz
3111 */
3112 if (problem == 0 || !fix_problem(ctx, problem, pctx))
3113 return;
3114
3115 /* simple remove all possible EA(s) */
3116 *((__u32 *)start) = 0UL;
3117 e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
3118 EXT2_INODE_SIZE(sb), "pass1");
3119}
3120
3121static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
3122{
3123 struct ext2_super_block *sb = ctx->fs->super;
3124 struct ext2_inode_large *inode;
3125 __u32 *eamagic;
3126 int min, max;
3127
3128 inode = (struct ext2_inode_large *) pctx->inode;
3129 if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
3130 /* this isn't large inode. so, nothing to check */
3131 return;
3132 }
3133
3134 /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
3135 min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
3136 max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
3137 /*
3138 * For now we will allow i_extra_isize to be 0, but really
3139 * implementations should never allow i_extra_isize to be 0
3140 */
3141 if (inode->i_extra_isize &&
3142 (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
3143 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
3144 return;
3145 inode->i_extra_isize = min;
3146 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
3147 EXT2_INODE_SIZE(sb), "pass1");
3148 return;
3149 }
3150
3151 eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3152 inode->i_extra_isize);
3153 if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
3154 /* it seems inode has an extended attribute(s) in body */
3155 check_ea_in_inode(ctx, pctx);
3156 }
3157}
3158
3159static void e2fsck_pass1(e2fsck_t ctx)
3160{
3161 int i;
3162 __u64 max_sizes;
3163 ext2_filsys fs = ctx->fs;
3164 ext2_ino_t ino;
3165 struct ext2_inode *inode;
3166 ext2_inode_scan scan;
3167 char *block_buf;
3168 unsigned char frag, fsize;
3169 struct problem_context pctx;
3170 struct scan_callback_struct scan_struct;
3171 struct ext2_super_block *sb = ctx->fs->super;
3172 int imagic_fs;
3173 int busted_fs_time = 0;
3174 int inode_size;
3175
3176 clear_problem_context(&pctx);
3177
3178 if (!(ctx->options & E2F_OPT_PREEN))
3179 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
3180
3181 if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
3182 !(ctx->options & E2F_OPT_NO)) {
3183 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
3184 ctx->dirs_to_hash = 0;
3185 }
3186
3187 /* Pass 1 */
3188
3189#define EXT2_BPP(bits) (1ULL << ((bits) - 2))
3190
3191 for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
3192 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
3193 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
3194 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
3195 max_sizes = (max_sizes * (1UL << i)) - 1;
3196 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
3197 }
3198#undef EXT2_BPP
3199
3200 imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
3201
3202 /*
3203 * Allocate bitmaps structures
3204 */
3205 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
3206 &ctx->inode_used_map);
3207 if (pctx.errcode) {
3208 pctx.num = 1;
3209 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3210 ctx->flags |= E2F_FLAG_ABORT;
3211 return;
3212 }
3213 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3214 _("directory inode map"), &ctx->inode_dir_map);
3215 if (pctx.errcode) {
3216 pctx.num = 2;
3217 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3218 ctx->flags |= E2F_FLAG_ABORT;
3219 return;
3220 }
3221 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3222 _("regular file inode map"), &ctx->inode_reg_map);
3223 if (pctx.errcode) {
3224 pctx.num = 6;
3225 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3226 ctx->flags |= E2F_FLAG_ABORT;
3227 return;
3228 }
3229 pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
3230 &ctx->block_found_map);
3231 if (pctx.errcode) {
3232 pctx.num = 1;
3233 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3234 ctx->flags |= E2F_FLAG_ABORT;
3235 return;
3236 }
3237 pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
3238 &ctx->inode_link_info);
3239 if (pctx.errcode) {
3240 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
3241 ctx->flags |= E2F_FLAG_ABORT;
3242 return;
3243 }
3244 inode_size = EXT2_INODE_SIZE(fs->super);
3245 inode = (struct ext2_inode *)
3246 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
3247
3248 inodes_to_process = (struct process_inode_block *)
3249 e2fsck_allocate_memory(ctx,
3250 (ctx->process_inode_size *
3251 sizeof(struct process_inode_block)),
3252 "array of inodes to process");
3253 process_inode_count = 0;
3254
3255 pctx.errcode = ext2fs_init_dblist(fs, 0);
3256 if (pctx.errcode) {
3257 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
3258 ctx->flags |= E2F_FLAG_ABORT;
3259 return;
3260 }
3261
3262 /*
3263 * If the last orphan field is set, clear it, since the pass1
3264 * processing will automatically find and clear the orphans.
3265 * In the future, we may want to try using the last_orphan
3266 * linked list ourselves, but for now, we clear it so that the
3267 * ext3 mount code won't get confused.
3268 */
3269 if (!(ctx->options & E2F_OPT_READONLY)) {
3270 if (fs->super->s_last_orphan) {
3271 fs->super->s_last_orphan = 0;
3272 ext2fs_mark_super_dirty(fs);
3273 }
3274 }
3275
3276 mark_table_blocks(ctx);
3277 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
3278 "block interate buffer");
3279 e2fsck_use_inode_shortcuts(ctx, 1);
3280 ehandler_operation(_("doing inode scan"));
3281 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
3282 &scan);
3283 if (pctx.errcode) {
3284 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3285 ctx->flags |= E2F_FLAG_ABORT;
3286 return;
3287 }
3288 ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
3289 ctx->stashed_inode = inode;
3290 scan_struct.ctx = ctx;
3291 scan_struct.block_buf = block_buf;
3292 ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
3293 if (ctx->progress)
3294 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
3295 return;
3296 if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
3297 (fs->super->s_mtime < fs->super->s_inodes_count))
3298 busted_fs_time = 1;
3299
3300 while (1) {
3301 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
3302 inode, inode_size);
3303 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3304 return;
3305 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
3306 continue;
3307 }
3308 if (pctx.errcode) {
3309 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3310 ctx->flags |= E2F_FLAG_ABORT;
3311 return;
3312 }
3313 if (!ino)
3314 break;
3315 pctx.ino = ino;
3316 pctx.inode = inode;
3317 ctx->stashed_ino = ino;
3318 if (inode->i_links_count) {
3319 pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
3320 ino, inode->i_links_count);
3321 if (pctx.errcode) {
3322 pctx.num = inode->i_links_count;
3323 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
3324 ctx->flags |= E2F_FLAG_ABORT;
3325 return;
3326 }
3327 }
3328 if (ino == EXT2_BAD_INO) {
3329 struct process_block_struct_1 pb;
3330
3331 pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
3332 &pb.fs_meta_blocks);
3333 if (pctx.errcode) {
3334 pctx.num = 4;
3335 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3336 ctx->flags |= E2F_FLAG_ABORT;
3337 return;
3338 }
3339 pb.ino = EXT2_BAD_INO;
3340 pb.num_blocks = pb.last_block = 0;
3341 pb.num_illegal_blocks = 0;
3342 pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
3343 pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
3344 pb.inode = inode;
3345 pb.pctx = &pctx;
3346 pb.ctx = ctx;
3347 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
3348 block_buf, process_bad_block, &pb);
3349 ext2fs_free_block_bitmap(pb.fs_meta_blocks);
3350 if (pctx.errcode) {
3351 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
3352 ctx->flags |= E2F_FLAG_ABORT;
3353 return;
3354 }
3355 if (pb.bbcheck)
3356 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
3357 ctx->flags |= E2F_FLAG_ABORT;
3358 return;
3359 }
3360 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3361 clear_problem_context(&pctx);
3362 continue;
3363 } else if (ino == EXT2_ROOT_INO) {
3364 /*
3365 * Make sure the root inode is a directory; if
3366 * not, offer to clear it. It will be
3367 * regnerated in pass #3.
3368 */
3369 if (!LINUX_S_ISDIR(inode->i_mode)) {
3370 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
Denis Vlasenko04158e02009-02-02 10:48:06 +00003371 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003372 inode->i_links_count = 0;
3373 ext2fs_icount_store(ctx->inode_link_info,
3374 ino, 0);
3375 e2fsck_write_inode(ctx, ino, inode,
3376 "pass1");
3377 }
3378
3379 }
3380 /*
3381 * If dtime is set, offer to clear it. mke2fs
3382 * version 0.2b created filesystems with the
3383 * dtime field set for the root and lost+found
3384 * directories. We won't worry about
3385 * /lost+found, since that can be regenerated
3386 * easily. But we will fix the root directory
3387 * as a special case.
3388 */
3389 if (inode->i_dtime && inode->i_links_count) {
3390 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
3391 inode->i_dtime = 0;
3392 e2fsck_write_inode(ctx, ino, inode,
3393 "pass1");
3394 }
3395 }
3396 } else if (ino == EXT2_JOURNAL_INO) {
3397 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3398 if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
3399 if (!LINUX_S_ISREG(inode->i_mode) &&
3400 fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
3401 &pctx)) {
3402 inode->i_mode = LINUX_S_IFREG;
3403 e2fsck_write_inode(ctx, ino, inode,
3404 "pass1");
3405 }
3406 check_blocks(ctx, &pctx, block_buf);
3407 continue;
3408 }
3409 if ((inode->i_links_count || inode->i_blocks ||
3410 inode->i_blocks || inode->i_block[0]) &&
3411 fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
3412 &pctx)) {
3413 memset(inode, 0, inode_size);
3414 ext2fs_icount_store(ctx->inode_link_info,
3415 ino, 0);
3416 e2fsck_write_inode_full(ctx, ino, inode,
3417 inode_size, "pass1");
3418 }
3419 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
3420 int problem = 0;
3421
3422 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3423 if (ino == EXT2_BOOT_LOADER_INO) {
3424 if (LINUX_S_ISDIR(inode->i_mode))
3425 problem = PR_1_RESERVED_BAD_MODE;
3426 } else if (ino == EXT2_RESIZE_INO) {
3427 if (inode->i_mode &&
3428 !LINUX_S_ISREG(inode->i_mode))
3429 problem = PR_1_RESERVED_BAD_MODE;
3430 } else {
3431 if (inode->i_mode != 0)
3432 problem = PR_1_RESERVED_BAD_MODE;
3433 }
3434 if (problem) {
3435 if (fix_problem(ctx, problem, &pctx)) {
3436 inode->i_mode = 0;
3437 e2fsck_write_inode(ctx, ino, inode,
3438 "pass1");
3439 }
3440 }
3441 check_blocks(ctx, &pctx, block_buf);
3442 continue;
3443 }
3444 /*
3445 * Check for inodes who might have been part of the
3446 * orphaned list linked list. They should have gotten
3447 * dealt with by now, unless the list had somehow been
3448 * corrupted.
3449 *
3450 * FIXME: In the future, inodes which are still in use
3451 * (and which are therefore) pending truncation should
3452 * be handled specially. Right now we just clear the
3453 * dtime field, and the normal e2fsck handling of
3454 * inodes where i_size and the inode blocks are
3455 * inconsistent is to fix i_size, instead of releasing
3456 * the extra blocks. This won't catch the inodes that
3457 * was at the end of the orphan list, but it's better
3458 * than nothing. The right answer is that there
3459 * shouldn't be any bugs in the orphan list handling. :-)
3460 */
3461 if (inode->i_dtime && !busted_fs_time &&
3462 inode->i_dtime < ctx->fs->super->s_inodes_count) {
3463 if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
3464 inode->i_dtime = inode->i_links_count ?
Denis Vlasenko04158e02009-02-02 10:48:06 +00003465 0 : time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003466 e2fsck_write_inode(ctx, ino, inode,
3467 "pass1");
3468 }
3469 }
3470
3471 /*
3472 * This code assumes that deleted inodes have
3473 * i_links_count set to 0.
3474 */
3475 if (!inode->i_links_count) {
3476 if (!inode->i_dtime && inode->i_mode) {
3477 if (fix_problem(ctx,
3478 PR_1_ZERO_DTIME, &pctx)) {
Denis Vlasenko04158e02009-02-02 10:48:06 +00003479 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003480 e2fsck_write_inode(ctx, ino, inode,
3481 "pass1");
3482 }
3483 }
3484 continue;
3485 }
3486 /*
3487 * n.b. 0.3c ext2fs code didn't clear i_links_count for
3488 * deleted files. Oops.
3489 *
3490 * Since all new ext2 implementations get this right,
3491 * we now assume that the case of non-zero
3492 * i_links_count and non-zero dtime means that we
3493 * should keep the file, not delete it.
3494 *
3495 */
3496 if (inode->i_dtime) {
3497 if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
3498 inode->i_dtime = 0;
3499 e2fsck_write_inode(ctx, ino, inode, "pass1");
3500 }
3501 }
3502
3503 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3504 switch (fs->super->s_creator_os) {
3505 case EXT2_OS_LINUX:
3506 frag = inode->osd2.linux2.l_i_frag;
3507 fsize = inode->osd2.linux2.l_i_fsize;
3508 break;
3509 case EXT2_OS_HURD:
3510 frag = inode->osd2.hurd2.h_i_frag;
3511 fsize = inode->osd2.hurd2.h_i_fsize;
3512 break;
3513 case EXT2_OS_MASIX:
3514 frag = inode->osd2.masix2.m_i_frag;
3515 fsize = inode->osd2.masix2.m_i_fsize;
3516 break;
3517 default:
3518 frag = fsize = 0;
3519 }
3520
3521 if (inode->i_faddr || frag || fsize ||
3522 (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
3523 mark_inode_bad(ctx, ino);
3524 if (inode->i_flags & EXT2_IMAGIC_FL) {
3525 if (imagic_fs) {
3526 if (!ctx->inode_imagic_map)
3527 alloc_imagic_map(ctx);
3528 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
3529 ino);
3530 } else {
3531 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
3532 inode->i_flags &= ~EXT2_IMAGIC_FL;
3533 e2fsck_write_inode(ctx, ino,
3534 inode, "pass1");
3535 }
3536 }
3537 }
3538
3539 check_inode_extra_space(ctx, &pctx);
3540
3541 if (LINUX_S_ISDIR(inode->i_mode)) {
3542 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
3543 e2fsck_add_dir_info(ctx, ino, 0);
3544 ctx->fs_directory_count++;
3545 } else if (LINUX_S_ISREG (inode->i_mode)) {
3546 ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
3547 ctx->fs_regular_count++;
3548 } else if (LINUX_S_ISCHR (inode->i_mode) &&
3549 e2fsck_pass1_check_device_inode(fs, inode)) {
3550 check_immutable(ctx, &pctx);
3551 check_size(ctx, &pctx);
3552 ctx->fs_chardev_count++;
3553 } else if (LINUX_S_ISBLK (inode->i_mode) &&
3554 e2fsck_pass1_check_device_inode(fs, inode)) {
3555 check_immutable(ctx, &pctx);
3556 check_size(ctx, &pctx);
3557 ctx->fs_blockdev_count++;
3558 } else if (LINUX_S_ISLNK (inode->i_mode) &&
3559 e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
3560 check_immutable(ctx, &pctx);
3561 ctx->fs_symlinks_count++;
3562 if (ext2fs_inode_data_blocks(fs, inode) == 0) {
3563 ctx->fs_fast_symlinks_count++;
3564 check_blocks(ctx, &pctx, block_buf);
3565 continue;
3566 }
3567 }
3568 else if (LINUX_S_ISFIFO (inode->i_mode) &&
3569 e2fsck_pass1_check_device_inode(fs, inode)) {
3570 check_immutable(ctx, &pctx);
3571 check_size(ctx, &pctx);
3572 ctx->fs_fifo_count++;
3573 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
3574 e2fsck_pass1_check_device_inode(fs, inode)) {
3575 check_immutable(ctx, &pctx);
3576 check_size(ctx, &pctx);
3577 ctx->fs_sockets_count++;
3578 } else
3579 mark_inode_bad(ctx, ino);
3580 if (inode->i_block[EXT2_IND_BLOCK])
3581 ctx->fs_ind_count++;
3582 if (inode->i_block[EXT2_DIND_BLOCK])
3583 ctx->fs_dind_count++;
3584 if (inode->i_block[EXT2_TIND_BLOCK])
3585 ctx->fs_tind_count++;
3586 if (inode->i_block[EXT2_IND_BLOCK] ||
3587 inode->i_block[EXT2_DIND_BLOCK] ||
3588 inode->i_block[EXT2_TIND_BLOCK] ||
3589 inode->i_file_acl) {
3590 inodes_to_process[process_inode_count].ino = ino;
3591 inodes_to_process[process_inode_count].inode = *inode;
3592 process_inode_count++;
3593 } else
3594 check_blocks(ctx, &pctx, block_buf);
3595
3596 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3597 return;
3598
3599 if (process_inode_count >= ctx->process_inode_size) {
3600 process_inodes(ctx, block_buf);
3601
3602 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3603 return;
3604 }
3605 }
3606 process_inodes(ctx, block_buf);
3607 ext2fs_close_inode_scan(scan);
3608 ehandler_operation(0);
3609
3610 /*
3611 * If any extended attribute blocks' reference counts need to
3612 * be adjusted, either up (ctx->refcount_extra), or down
3613 * (ctx->refcount), then fix them.
3614 */
3615 if (ctx->refcount) {
3616 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
3617 ea_refcount_free(ctx->refcount);
3618 ctx->refcount = 0;
3619 }
3620 if (ctx->refcount_extra) {
3621 adjust_extattr_refcount(ctx, ctx->refcount_extra,
3622 block_buf, +1);
3623 ea_refcount_free(ctx->refcount_extra);
3624 ctx->refcount_extra = 0;
3625 }
3626
3627 if (ctx->invalid_bitmaps)
3628 handle_fs_bad_blocks(ctx);
3629
3630 /* We don't need the block_ea_map any more */
3631 ext2fs_free_block_bitmap(ctx->block_ea_map);
3632 ctx->block_ea_map = 0;
3633
3634 if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
3635 ext2fs_block_bitmap save_bmap;
3636
3637 save_bmap = fs->block_map;
3638 fs->block_map = ctx->block_found_map;
3639 clear_problem_context(&pctx);
3640 pctx.errcode = ext2fs_create_resize_inode(fs);
3641 if (pctx.errcode) {
3642 fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
3643 /* Should never get here */
3644 ctx->flags |= E2F_FLAG_ABORT;
3645 return;
3646 }
3647 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
3648 "recreate inode");
Denis Vlasenko04158e02009-02-02 10:48:06 +00003649 inode->i_mtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003650 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
3651 "recreate inode");
3652 fs->block_map = save_bmap;
3653 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
3654 }
3655
3656 if (ctx->flags & E2F_FLAG_RESTART) {
3657 /*
3658 * Only the master copy of the superblock and block
3659 * group descriptors are going to be written during a
3660 * restart, so set the superblock to be used to be the
3661 * master superblock.
3662 */
3663 ctx->use_superblock = 0;
3664 unwind_pass1();
3665 goto endit;
3666 }
3667
3668 if (ctx->block_dup_map) {
3669 if (ctx->options & E2F_OPT_PREEN) {
3670 clear_problem_context(&pctx);
3671 fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
3672 }
3673 e2fsck_pass1_dupblocks(ctx, block_buf);
3674 }
3675 ext2fs_free_mem(&inodes_to_process);
3676endit:
3677 e2fsck_use_inode_shortcuts(ctx, 0);
3678
3679 ext2fs_free_mem(&block_buf);
3680 ext2fs_free_mem(&inode);
3681
3682}
3683
3684/*
3685 * When the inode_scan routines call this callback at the end of the
3686 * glock group, call process_inodes.
3687 */
3688static errcode_t scan_callback(ext2_filsys fs,
3689 dgrp_t group, void * priv_data)
3690{
3691 struct scan_callback_struct *scan_struct;
3692 e2fsck_t ctx;
3693
3694 scan_struct = (struct scan_callback_struct *) priv_data;
3695 ctx = scan_struct->ctx;
3696
3697 process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
3698
3699 if (ctx->progress)
3700 if ((ctx->progress)(ctx, 1, group+1,
3701 ctx->fs->group_desc_count))
3702 return EXT2_ET_CANCEL_REQUESTED;
3703
3704 return 0;
3705}
3706
3707/*
3708 * Process the inodes in the "inodes to process" list.
3709 */
3710static void process_inodes(e2fsck_t ctx, char *block_buf)
3711{
3712 int i;
3713 struct ext2_inode *old_stashed_inode;
3714 ext2_ino_t old_stashed_ino;
3715 const char *old_operation;
3716 char buf[80];
3717 struct problem_context pctx;
3718
3719 /* begin process_inodes */
3720 if (process_inode_count == 0)
3721 return;
3722 old_operation = ehandler_operation(0);
3723 old_stashed_inode = ctx->stashed_inode;
3724 old_stashed_ino = ctx->stashed_ino;
3725 qsort(inodes_to_process, process_inode_count,
3726 sizeof(struct process_inode_block), process_inode_cmp);
3727 clear_problem_context(&pctx);
3728 for (i=0; i < process_inode_count; i++) {
3729 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
3730 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
3731 sprintf(buf, _("reading indirect blocks of inode %u"),
3732 pctx.ino);
3733 ehandler_operation(buf);
3734 check_blocks(ctx, &pctx, block_buf);
3735 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3736 break;
3737 }
3738 ctx->stashed_inode = old_stashed_inode;
3739 ctx->stashed_ino = old_stashed_ino;
3740 process_inode_count = 0;
3741 /* end process inodes */
3742
3743 ehandler_operation(old_operation);
3744}
3745
3746static int process_inode_cmp(const void *a, const void *b)
3747{
3748 const struct process_inode_block *ib_a =
3749 (const struct process_inode_block *) a;
3750 const struct process_inode_block *ib_b =
3751 (const struct process_inode_block *) b;
3752 int ret;
3753
3754 ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
3755 ib_b->inode.i_block[EXT2_IND_BLOCK]);
3756 if (ret == 0)
3757 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
3758 return ret;
3759}
3760
3761/*
3762 * Mark an inode as being bad in some what
3763 */
3764static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
3765{
3766 struct problem_context pctx;
3767
3768 if (!ctx->inode_bad_map) {
3769 clear_problem_context(&pctx);
3770
3771 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3772 _("bad inode map"), &ctx->inode_bad_map);
3773 if (pctx.errcode) {
3774 pctx.num = 3;
3775 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3776 /* Should never get here */
3777 ctx->flags |= E2F_FLAG_ABORT;
3778 return;
3779 }
3780 }
3781 ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
3782}
3783
3784
3785/*
3786 * This procedure will allocate the inode imagic table
3787 */
3788static void alloc_imagic_map(e2fsck_t ctx)
3789{
3790 struct problem_context pctx;
3791
3792 clear_problem_context(&pctx);
3793 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3794 _("imagic inode map"),
3795 &ctx->inode_imagic_map);
3796 if (pctx.errcode) {
3797 pctx.num = 5;
3798 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3799 /* Should never get here */
3800 ctx->flags |= E2F_FLAG_ABORT;
3801 return;
3802 }
3803}
3804
3805/*
3806 * Marks a block as in use, setting the dup_map if it's been set
3807 * already. Called by process_block and process_bad_block.
3808 *
3809 * WARNING: Assumes checks have already been done to make sure block
3810 * is valid. This is true in both process_block and process_bad_block.
3811 */
3812static void mark_block_used(e2fsck_t ctx, blk_t block)
3813{
3814 struct problem_context pctx;
3815
3816 clear_problem_context(&pctx);
3817
3818 if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
3819 if (!ctx->block_dup_map) {
3820 pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
3821 _("multiply claimed block map"),
3822 &ctx->block_dup_map);
3823 if (pctx.errcode) {
3824 pctx.num = 3;
3825 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
3826 &pctx);
3827 /* Should never get here */
3828 ctx->flags |= E2F_FLAG_ABORT;
3829 return;
3830 }
3831 }
3832 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
3833 } else {
3834 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
3835 }
3836}
3837
3838/*
3839 * Adjust the extended attribute block's reference counts at the end
3840 * of pass 1, either by subtracting out references for EA blocks that
3841 * are still referenced in ctx->refcount, or by adding references for
3842 * EA blocks that had extra references as accounted for in
3843 * ctx->refcount_extra.
3844 */
3845static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3846 char *block_buf, int adjust_sign)
3847{
3848 struct ext2_ext_attr_header *header;
3849 struct problem_context pctx;
3850 ext2_filsys fs = ctx->fs;
3851 blk_t blk;
3852 __u32 should_be;
3853 int count;
3854
3855 clear_problem_context(&pctx);
3856
3857 ea_refcount_intr_begin(refcount);
3858 while (1) {
3859 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
3860 break;
3861 pctx.blk = blk;
3862 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3863 if (pctx.errcode) {
3864 fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
3865 return;
3866 }
3867 header = (struct ext2_ext_attr_header *) block_buf;
3868 pctx.blkcount = header->h_refcount;
3869 should_be = header->h_refcount + adjust_sign * count;
3870 pctx.num = should_be;
3871 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
3872 header->h_refcount = should_be;
3873 pctx.errcode = ext2fs_write_ext_attr(fs, blk,
3874 block_buf);
3875 if (pctx.errcode) {
3876 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
3877 continue;
3878 }
3879 }
3880 }
3881}
3882
3883/*
3884 * Handle processing the extended attribute blocks
3885 */
3886static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
3887 char *block_buf)
3888{
3889 ext2_filsys fs = ctx->fs;
3890 ext2_ino_t ino = pctx->ino;
3891 struct ext2_inode *inode = pctx->inode;
3892 blk_t blk;
3893 char * end;
3894 struct ext2_ext_attr_header *header;
3895 struct ext2_ext_attr_entry *entry;
3896 int count;
3897 region_t region;
3898
3899 blk = inode->i_file_acl;
3900 if (blk == 0)
3901 return 0;
3902
3903 /*
3904 * If the Extended attribute flag isn't set, then a non-zero
3905 * file acl means that the inode is corrupted.
3906 *
3907 * Or if the extended attribute block is an invalid block,
3908 * then the inode is also corrupted.
3909 */
3910 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
3911 (blk < fs->super->s_first_data_block) ||
3912 (blk >= fs->super->s_blocks_count)) {
3913 mark_inode_bad(ctx, ino);
3914 return 0;
3915 }
3916
3917 /* If ea bitmap hasn't been allocated, create it */
3918 if (!ctx->block_ea_map) {
3919 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
3920 _("ext attr block map"),
3921 &ctx->block_ea_map);
3922 if (pctx->errcode) {
3923 pctx->num = 2;
3924 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
3925 ctx->flags |= E2F_FLAG_ABORT;
3926 return 0;
3927 }
3928 }
3929
3930 /* Create the EA refcount structure if necessary */
3931 if (!ctx->refcount) {
3932 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
3933 if (pctx->errcode) {
3934 pctx->num = 1;
3935 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3936 ctx->flags |= E2F_FLAG_ABORT;
3937 return 0;
3938 }
3939 }
3940
3941 /* Have we seen this EA block before? */
3942 if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
3943 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
3944 return 1;
3945 /* Ooops, this EA was referenced more than it stated */
3946 if (!ctx->refcount_extra) {
3947 pctx->errcode = ea_refcount_create(0,
3948 &ctx->refcount_extra);
3949 if (pctx->errcode) {
3950 pctx->num = 2;
3951 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3952 ctx->flags |= E2F_FLAG_ABORT;
3953 return 0;
3954 }
3955 }
3956 ea_refcount_increment(ctx->refcount_extra, blk, 0);
3957 return 1;
3958 }
3959
3960 /*
3961 * OK, we haven't seen this EA block yet. So we need to
3962 * validate it
3963 */
3964 pctx->blk = blk;
3965 pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3966 if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
3967 goto clear_extattr;
3968 header = (struct ext2_ext_attr_header *) block_buf;
3969 pctx->blk = inode->i_file_acl;
3970 if (((ctx->ext_attr_ver == 1) &&
3971 (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
3972 ((ctx->ext_attr_ver == 2) &&
3973 (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
3974 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
3975 goto clear_extattr;
3976 }
3977
3978 if (header->h_blocks != 1) {
3979 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
3980 goto clear_extattr;
3981 }
3982
3983 region = region_create(0, fs->blocksize);
3984 if (!region) {
3985 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
3986 ctx->flags |= E2F_FLAG_ABORT;
3987 return 0;
3988 }
3989 if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
3990 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
3991 goto clear_extattr;
3992 }
3993
3994 entry = (struct ext2_ext_attr_entry *)(header+1);
3995 end = block_buf + fs->blocksize;
3996 while ((char *)entry < end && *(__u32 *)entry) {
3997 if (region_allocate(region, (char *)entry - (char *)header,
3998 EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
3999 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4000 goto clear_extattr;
4001 }
4002 if ((ctx->ext_attr_ver == 1 &&
4003 (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
4004 (ctx->ext_attr_ver == 2 &&
4005 entry->e_name_index == 0)) {
4006 if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
4007 goto clear_extattr;
4008 }
4009 if (entry->e_value_block != 0) {
4010 if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
4011 goto clear_extattr;
4012 }
4013 if (entry->e_value_size &&
4014 region_allocate(region, entry->e_value_offs,
4015 EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
4016 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4017 goto clear_extattr;
4018 }
4019 entry = EXT2_EXT_ATTR_NEXT(entry);
4020 }
4021 if (region_allocate(region, (char *)entry - (char *)header, 4)) {
4022 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4023 goto clear_extattr;
4024 }
4025 region_free(region);
4026
4027 count = header->h_refcount - 1;
4028 if (count)
4029 ea_refcount_store(ctx->refcount, blk, count);
4030 mark_block_used(ctx, blk);
4031 ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
4032
4033 return 1;
4034
4035clear_extattr:
4036 inode->i_file_acl = 0;
4037 e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
4038 return 0;
4039}
4040
4041/* Returns 1 if bad htree, 0 if OK */
4042static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
4043 ext2_ino_t ino FSCK_ATTR((unused)),
4044 struct ext2_inode *inode,
4045 char *block_buf)
4046{
4047 struct ext2_dx_root_info *root;
4048 ext2_filsys fs = ctx->fs;
4049 errcode_t retval;
4050 blk_t blk;
4051
4052 if ((!LINUX_S_ISDIR(inode->i_mode) &&
4053 fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
4054 (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4055 fix_problem(ctx, PR_1_HTREE_SET, pctx)))
4056 return 1;
4057
4058 blk = inode->i_block[0];
4059 if (((blk == 0) ||
4060 (blk < fs->super->s_first_data_block) ||
4061 (blk >= fs->super->s_blocks_count)) &&
4062 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4063 return 1;
4064
4065 retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
4066 if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4067 return 1;
4068
4069 /* XXX should check that beginning matches a directory */
4070 root = (struct ext2_dx_root_info *) (block_buf + 24);
4071
4072 if ((root->reserved_zero || root->info_length < 8) &&
4073 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4074 return 1;
4075
4076 pctx->num = root->hash_version;
4077 if ((root->hash_version != EXT2_HASH_LEGACY) &&
4078 (root->hash_version != EXT2_HASH_HALF_MD4) &&
4079 (root->hash_version != EXT2_HASH_TEA) &&
4080 fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
4081 return 1;
4082
4083 if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
4084 fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
4085 return 1;
4086
4087 pctx->num = root->indirect_levels;
4088 if ((root->indirect_levels > 1) &&
4089 fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
4090 return 1;
4091
4092 return 0;
4093}
4094
4095/*
4096 * This subroutine is called on each inode to account for all of the
4097 * blocks used by that inode.
4098 */
4099static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4100 char *block_buf)
4101{
4102 ext2_filsys fs = ctx->fs;
4103 struct process_block_struct_1 pb;
4104 ext2_ino_t ino = pctx->ino;
4105 struct ext2_inode *inode = pctx->inode;
4106 int bad_size = 0;
4107 int dirty_inode = 0;
4108 __u64 size;
4109
4110 pb.ino = ino;
4111 pb.num_blocks = 0;
4112 pb.last_block = -1;
4113 pb.num_illegal_blocks = 0;
4114 pb.suppress = 0; pb.clear = 0;
4115 pb.fragmented = 0;
4116 pb.compressed = 0;
4117 pb.previous_block = 0;
4118 pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
4119 pb.is_reg = LINUX_S_ISREG(inode->i_mode);
4120 pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
4121 pb.inode = inode;
4122 pb.pctx = pctx;
4123 pb.ctx = ctx;
4124 pctx->ino = ino;
4125 pctx->errcode = 0;
4126
4127 if (inode->i_flags & EXT2_COMPRBLK_FL) {
4128 if (fs->super->s_feature_incompat &
4129 EXT2_FEATURE_INCOMPAT_COMPRESSION)
4130 pb.compressed = 1;
4131 else {
4132 if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
4133 inode->i_flags &= ~EXT2_COMPRBLK_FL;
4134 dirty_inode++;
4135 }
4136 }
4137 }
4138
4139 if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
4140 pb.num_blocks++;
4141
4142 if (ext2fs_inode_has_valid_blocks(inode))
4143 pctx->errcode = ext2fs_block_iterate2(fs, ino,
4144 pb.is_dir ? BLOCK_FLAG_HOLE : 0,
4145 block_buf, process_block, &pb);
4146 end_problem_latch(ctx, PR_LATCH_BLOCK);
4147 end_problem_latch(ctx, PR_LATCH_TOOBIG);
4148 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4149 goto out;
4150 if (pctx->errcode)
4151 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
4152
4153 if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
4154 ctx->fs_fragmented++;
4155
4156 if (pb.clear) {
4157 inode->i_links_count = 0;
4158 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
Denis Vlasenko04158e02009-02-02 10:48:06 +00004159 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004160 dirty_inode++;
4161 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4162 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4163 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4164 /*
4165 * The inode was probably partially accounted for
4166 * before processing was aborted, so we need to
4167 * restart the pass 1 scan.
4168 */
4169 ctx->flags |= E2F_FLAG_RESTART;
4170 goto out;
4171 }
4172
4173 if (inode->i_flags & EXT2_INDEX_FL) {
4174 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
4175 inode->i_flags &= ~EXT2_INDEX_FL;
4176 dirty_inode++;
4177 } else {
4178#ifdef ENABLE_HTREE
4179 e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
4180#endif
4181 }
4182 }
4183 if (ctx->dirs_to_hash && pb.is_dir &&
4184 !(inode->i_flags & EXT2_INDEX_FL) &&
4185 ((inode->i_size / fs->blocksize) >= 3))
4186 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
4187
4188 if (!pb.num_blocks && pb.is_dir) {
4189 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
4190 inode->i_links_count = 0;
4191 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
Denis Vlasenko04158e02009-02-02 10:48:06 +00004192 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004193 dirty_inode++;
4194 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4195 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4196 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4197 ctx->fs_directory_count--;
4198 goto out;
4199 }
4200 }
4201
4202 pb.num_blocks *= (fs->blocksize / 512);
4203
4204 if (pb.is_dir) {
4205 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
4206 if (nblock > (pb.last_block + 1))
4207 bad_size = 1;
4208 else if (nblock < (pb.last_block + 1)) {
4209 if (((pb.last_block + 1) - nblock) >
4210 fs->super->s_prealloc_dir_blocks)
4211 bad_size = 2;
4212 }
4213 } else {
4214 size = EXT2_I_SIZE(inode);
4215 if ((pb.last_block >= 0) &&
4216 (size < (__u64) pb.last_block * fs->blocksize))
4217 bad_size = 3;
4218 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
4219 bad_size = 4;
4220 }
4221 /* i_size for symlinks is checked elsewhere */
4222 if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
4223 pctx->num = (pb.last_block+1) * fs->blocksize;
4224 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
4225 inode->i_size = pctx->num;
4226 if (!LINUX_S_ISDIR(inode->i_mode))
4227 inode->i_size_high = pctx->num >> 32;
4228 dirty_inode++;
4229 }
4230 pctx->num = 0;
4231 }
4232 if (LINUX_S_ISREG(inode->i_mode) &&
4233 (inode->i_size_high || inode->i_size & 0x80000000UL))
4234 ctx->large_files++;
4235 if (pb.num_blocks != inode->i_blocks) {
4236 pctx->num = pb.num_blocks;
4237 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
4238 inode->i_blocks = pb.num_blocks;
4239 dirty_inode++;
4240 }
4241 pctx->num = 0;
4242 }
4243out:
4244 if (dirty_inode)
4245 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
4246}
4247
4248
4249/*
4250 * This is a helper function for check_blocks().
4251 */
4252static int process_block(ext2_filsys fs,
4253 blk_t *block_nr,
4254 e2_blkcnt_t blockcnt,
4255 blk_t ref_block FSCK_ATTR((unused)),
4256 int ref_offset FSCK_ATTR((unused)),
4257 void *priv_data)
4258{
4259 struct process_block_struct_1 *p;
4260 struct problem_context *pctx;
4261 blk_t blk = *block_nr;
4262 int ret_code = 0;
4263 int problem = 0;
4264 e2fsck_t ctx;
4265
4266 p = (struct process_block_struct_1 *) priv_data;
4267 pctx = p->pctx;
4268 ctx = p->ctx;
4269
4270 if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
4271 /* todo: Check that the comprblk_fl is high, that the
4272 blkaddr pattern looks right (all non-holes up to
4273 first EXT2FS_COMPRESSED_BLKADDR, then all
4274 EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
4275 that the feature_incompat bit is high, and that the
4276 inode is a regular file. If we're doing a "full
4277 check" (a concept introduced to e2fsck by e2compr,
4278 meaning that we look at data blocks as well as
4279 metadata) then call some library routine that
4280 checks the compressed data. I'll have to think
4281 about this, because one particularly important
4282 problem to be able to fix is to recalculate the
4283 cluster size if necessary. I think that perhaps
4284 we'd better do most/all e2compr-specific checks
4285 separately, after the non-e2compr checks. If not
4286 doing a full check, it may be useful to test that
4287 the personality is linux; e.g. if it isn't then
4288 perhaps this really is just an illegal block. */
4289 return 0;
4290 }
4291
4292 if (blk == 0) {
4293 if (p->is_dir == 0) {
4294 /*
4295 * Should never happen, since only directories
4296 * get called with BLOCK_FLAG_HOLE
4297 */
4298#ifdef DEBUG_E2FSCK
4299 printf("process_block() called with blk == 0, "
4300 "blockcnt=%d, inode %lu???\n",
4301 blockcnt, p->ino);
4302#endif
4303 return 0;
4304 }
4305 if (blockcnt < 0)
4306 return 0;
4307 if (blockcnt * fs->blocksize < p->inode->i_size) {
4308 goto mark_dir;
4309 }
4310 return 0;
4311 }
4312
4313 /*
4314 * Simplistic fragmentation check. We merely require that the
4315 * file be contiguous. (Which can never be true for really
4316 * big files that are greater than a block group.)
4317 */
4318 if (!HOLE_BLKADDR(p->previous_block)) {
4319 if (p->previous_block+1 != blk)
4320 p->fragmented = 1;
4321 }
4322 p->previous_block = blk;
4323
4324 if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
4325 problem = PR_1_TOOBIG_DIR;
4326 if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
4327 problem = PR_1_TOOBIG_REG;
4328 if (!p->is_dir && !p->is_reg && blockcnt > 0)
4329 problem = PR_1_TOOBIG_SYMLINK;
4330
4331 if (blk < fs->super->s_first_data_block ||
4332 blk >= fs->super->s_blocks_count)
4333 problem = PR_1_ILLEGAL_BLOCK_NUM;
4334
4335 if (problem) {
4336 p->num_illegal_blocks++;
4337 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
4338 if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
4339 p->clear = 1;
4340 return BLOCK_ABORT;
4341 }
4342 if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
4343 p->suppress = 1;
4344 set_latch_flags(PR_LATCH_BLOCK,
4345 PRL_SUPPRESS, 0);
4346 }
4347 }
4348 pctx->blk = blk;
4349 pctx->blkcount = blockcnt;
4350 if (fix_problem(ctx, problem, pctx)) {
4351 blk = *block_nr = 0;
4352 ret_code = BLOCK_CHANGED;
4353 goto mark_dir;
4354 } else
4355 return 0;
4356 }
4357
4358 if (p->ino == EXT2_RESIZE_INO) {
4359 /*
4360 * The resize inode has already be sanity checked
4361 * during pass #0 (the superblock checks). All we
4362 * have to do is mark the double indirect block as
4363 * being in use; all of the other blocks are handled
4364 * by mark_table_blocks()).
4365 */
4366 if (blockcnt == BLOCK_COUNT_DIND)
4367 mark_block_used(ctx, blk);
4368 } else
4369 mark_block_used(ctx, blk);
4370 p->num_blocks++;
4371 if (blockcnt >= 0)
4372 p->last_block = blockcnt;
4373mark_dir:
4374 if (p->is_dir && (blockcnt >= 0)) {
4375 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
4376 blk, blockcnt);
4377 if (pctx->errcode) {
4378 pctx->blk = blk;
4379 pctx->num = blockcnt;
4380 fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
4381 /* Should never get here */
4382 ctx->flags |= E2F_FLAG_ABORT;
4383 return BLOCK_ABORT;
4384 }
4385 }
4386 return ret_code;
4387}
4388
4389static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
4390 blk_t *block_nr,
4391 e2_blkcnt_t blockcnt,
4392 blk_t ref_block FSCK_ATTR((unused)),
4393 int ref_offset FSCK_ATTR((unused)),
4394 void *priv_data EXT2FS_ATTR((unused)))
4395{
4396 /*
4397 * Note: This function processes blocks for the bad blocks
4398 * inode, which is never compressed. So we don't use HOLE_BLKADDR().
4399 */
4400
4401 printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
4402 return BLOCK_ERROR;
4403}
4404
4405/*
4406 * This routine gets called at the end of pass 1 if bad blocks are
4407 * detected in the superblock, group descriptors, inode_bitmaps, or
4408 * block bitmaps. At this point, all of the blocks have been mapped
4409 * out, so we can try to allocate new block(s) to replace the bad
4410 * blocks.
4411 */
4412static void handle_fs_bad_blocks(e2fsck_t ctx)
4413{
4414 printf("Bad blocks detected on your filesystem\n"
4415 "You should get your data off as the device will soon die\n");
4416}
4417
4418/*
4419 * This routine marks all blocks which are used by the superblock,
4420 * group descriptors, inode bitmaps, and block bitmaps.
4421 */
4422static void mark_table_blocks(e2fsck_t ctx)
4423{
4424 ext2_filsys fs = ctx->fs;
4425 blk_t block, b;
4426 dgrp_t i;
4427 int j;
4428 struct problem_context pctx;
4429
4430 clear_problem_context(&pctx);
4431
4432 block = fs->super->s_first_data_block;
4433 for (i = 0; i < fs->group_desc_count; i++) {
4434 pctx.group = i;
4435
4436 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
4437
4438 /*
4439 * Mark the blocks used for the inode table
4440 */
4441 if (fs->group_desc[i].bg_inode_table) {
4442 for (j = 0, b = fs->group_desc[i].bg_inode_table;
4443 j < fs->inode_blocks_per_group;
4444 j++, b++) {
4445 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4446 b)) {
4447 pctx.blk = b;
4448 if (fix_problem(ctx,
4449 PR_1_ITABLE_CONFLICT, &pctx)) {
4450 ctx->invalid_inode_table_flag[i]++;
4451 ctx->invalid_bitmaps++;
4452 }
4453 } else {
4454 ext2fs_mark_block_bitmap(ctx->block_found_map,
4455 b);
4456 }
4457 }
4458 }
4459
4460 /*
4461 * Mark block used for the block bitmap
4462 */
4463 if (fs->group_desc[i].bg_block_bitmap) {
4464 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4465 fs->group_desc[i].bg_block_bitmap)) {
4466 pctx.blk = fs->group_desc[i].bg_block_bitmap;
4467 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
4468 ctx->invalid_block_bitmap_flag[i]++;
4469 ctx->invalid_bitmaps++;
4470 }
4471 } else {
4472 ext2fs_mark_block_bitmap(ctx->block_found_map,
4473 fs->group_desc[i].bg_block_bitmap);
4474 }
4475
4476 }
4477 /*
4478 * Mark block used for the inode bitmap
4479 */
4480 if (fs->group_desc[i].bg_inode_bitmap) {
4481 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4482 fs->group_desc[i].bg_inode_bitmap)) {
4483 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
4484 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
4485 ctx->invalid_inode_bitmap_flag[i]++;
4486 ctx->invalid_bitmaps++;
4487 }
4488 } else {
4489 ext2fs_mark_block_bitmap(ctx->block_found_map,
4490 fs->group_desc[i].bg_inode_bitmap);
4491 }
4492 }
4493 block += fs->super->s_blocks_per_group;
4494 }
4495}
4496
4497/*
4498 * Thes subroutines short circuits ext2fs_get_blocks and
4499 * ext2fs_check_directory; we use them since we already have the inode
4500 * structure, so there's no point in letting the ext2fs library read
4501 * the inode again.
4502 */
4503static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
4504 blk_t *blocks)
4505{
4506 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4507 int i;
4508
4509 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4510 return EXT2_ET_CALLBACK_NOTHANDLED;
4511
4512 for (i=0; i < EXT2_N_BLOCKS; i++)
4513 blocks[i] = ctx->stashed_inode->i_block[i];
4514 return 0;
4515}
4516
4517static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
4518 struct ext2_inode *inode)
4519{
4520 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4521
4522 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4523 return EXT2_ET_CALLBACK_NOTHANDLED;
4524 *inode = *ctx->stashed_inode;
4525 return 0;
4526}
4527
4528static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
4529 struct ext2_inode *inode)
4530{
4531 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4532
4533 if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
4534 *ctx->stashed_inode = *inode;
4535 return EXT2_ET_CALLBACK_NOTHANDLED;
4536}
4537
4538static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
4539{
4540 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4541
4542 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4543 return EXT2_ET_CALLBACK_NOTHANDLED;
4544
4545 if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
4546 return EXT2_ET_NO_DIRECTORY;
4547 return 0;
4548}
4549
4550void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
4551{
4552 ext2_filsys fs = ctx->fs;
4553
4554 if (bool) {
4555 fs->get_blocks = pass1_get_blocks;
4556 fs->check_directory = pass1_check_directory;
4557 fs->read_inode = pass1_read_inode;
4558 fs->write_inode = pass1_write_inode;
4559 ctx->stashed_ino = 0;
4560 } else {
4561 fs->get_blocks = 0;
4562 fs->check_directory = 0;
4563 fs->read_inode = 0;
4564 fs->write_inode = 0;
4565 }
4566}
4567
4568/*
4569 * pass1b.c --- Pass #1b of e2fsck
4570 *
4571 * This file contains pass1B, pass1C, and pass1D of e2fsck. They are
4572 * only invoked if pass 1 discovered blocks which are in use by more
4573 * than one inode.
4574 *
4575 * Pass1B scans the data blocks of all the inodes again, generating a
4576 * complete list of duplicate blocks and which inodes have claimed
4577 * them.
4578 *
4579 * Pass1C does a tree-traversal of the filesystem, to determine the
4580 * parent directories of these inodes. This step is necessary so that
4581 * e2fsck can print out the pathnames of affected inodes.
4582 *
4583 * Pass1D is a reconciliation pass. For each inode with duplicate
4584 * blocks, the user is prompted if s/he would like to clone the file
4585 * (so that the file gets a fresh copy of the duplicated blocks) or
4586 * simply to delete the file.
4587 *
4588 */
4589
4590
4591/* Needed for architectures where sizeof(int) != sizeof(void *) */
4592#define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val))
4593#define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr))
4594
4595/* Define an extension to the ext2 library's block count information */
4596#define BLOCK_COUNT_EXTATTR (-5)
4597
4598struct block_el {
4599 blk_t block;
4600 struct block_el *next;
4601};
4602
4603struct inode_el {
4604 ext2_ino_t inode;
4605 struct inode_el *next;
4606};
4607
4608struct dup_block {
4609 int num_bad;
4610 struct inode_el *inode_list;
4611};
4612
4613/*
4614 * This structure stores information about a particular inode which
4615 * is sharing blocks with other inodes. This information is collected
4616 * to display to the user, so that the user knows what files he or she
4617 * is dealing with, when trying to decide how to resolve the conflict
4618 * of multiply-claimed blocks.
4619 */
4620struct dup_inode {
4621 ext2_ino_t dir;
4622 int num_dupblocks;
4623 struct ext2_inode inode;
4624 struct block_el *block_list;
4625};
4626
4627static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
4628 e2_blkcnt_t blockcnt, blk_t ref_blk,
4629 int ref_offset, void *priv_data);
4630static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
4631 struct dup_inode *dp, char *block_buf);
4632static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
4633 struct dup_inode *dp, char* block_buf);
4634static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
4635
4636static void pass1b(e2fsck_t ctx, char *block_buf);
4637static void pass1c(e2fsck_t ctx, char *block_buf);
4638static void pass1d(e2fsck_t ctx, char *block_buf);
4639
4640static int dup_inode_count = 0;
4641
4642static dict_t blk_dict, ino_dict;
4643
4644static ext2fs_inode_bitmap inode_dup_map;
4645
4646static int dict_int_cmp(const void *a, const void *b)
4647{
4648 intptr_t ia, ib;
4649
4650 ia = (intptr_t)a;
4651 ib = (intptr_t)b;
4652
4653 return (ia-ib);
4654}
4655
4656/*
4657 * Add a duplicate block record
4658 */
4659static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
4660 struct ext2_inode *inode)
4661{
4662 dnode_t *n;
4663 struct dup_block *db;
4664 struct dup_inode *di;
4665 struct block_el *blk_el;
4666 struct inode_el *ino_el;
4667
4668 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
4669 if (n)
4670 db = (struct dup_block *) dnode_get(n);
4671 else {
4672 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
4673 sizeof(struct dup_block), "duplicate block header");
4674 db->num_bad = 0;
4675 db->inode_list = 0;
4676 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
4677 }
4678 ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
4679 sizeof(struct inode_el), "inode element");
4680 ino_el->inode = ino;
4681 ino_el->next = db->inode_list;
4682 db->inode_list = ino_el;
4683 db->num_bad++;
4684
4685 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
4686 if (n)
4687 di = (struct dup_inode *) dnode_get(n);
4688 else {
4689 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
4690 sizeof(struct dup_inode), "duplicate inode header");
Denis Vlasenkob71c6682007-07-21 15:08:09 +00004691 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004692 di->num_dupblocks = 0;
4693 di->block_list = 0;
4694 di->inode = *inode;
4695 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
4696 }
4697 blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
4698 sizeof(struct block_el), "block element");
4699 blk_el->block = blk;
4700 blk_el->next = di->block_list;
4701 di->block_list = blk_el;
4702 di->num_dupblocks++;
4703}
4704
4705/*
4706 * Free a duplicate inode record
4707 */
4708static void inode_dnode_free(dnode_t *node)
4709{
4710 struct dup_inode *di;
4711 struct block_el *p, *next;
4712
4713 di = (struct dup_inode *) dnode_get(node);
4714 for (p = di->block_list; p; p = next) {
4715 next = p->next;
4716 free(p);
4717 }
4718 free(node);
4719}
4720
4721/*
4722 * Free a duplicate block record
4723 */
4724static void block_dnode_free(dnode_t *node)
4725{
4726 struct dup_block *db;
4727 struct inode_el *p, *next;
4728
4729 db = (struct dup_block *) dnode_get(node);
4730 for (p = db->inode_list; p; p = next) {
4731 next = p->next;
4732 free(p);
4733 }
4734 free(node);
4735}
4736
4737
4738/*
4739 * Main procedure for handling duplicate blocks
4740 */
4741void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
4742{
4743 ext2_filsys fs = ctx->fs;
4744 struct problem_context pctx;
4745
4746 clear_problem_context(&pctx);
4747
4748 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4749 _("multiply claimed inode map"), &inode_dup_map);
4750 if (pctx.errcode) {
4751 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
4752 ctx->flags |= E2F_FLAG_ABORT;
4753 return;
4754 }
4755
4756 dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4757 dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4758 dict_set_allocator(&ino_dict, inode_dnode_free);
4759 dict_set_allocator(&blk_dict, block_dnode_free);
4760
4761 pass1b(ctx, block_buf);
4762 pass1c(ctx, block_buf);
4763 pass1d(ctx, block_buf);
4764
4765 /*
4766 * Time to free all of the accumulated data structures that we
4767 * don't need anymore.
4768 */
4769 dict_free_nodes(&ino_dict);
4770 dict_free_nodes(&blk_dict);
4771}
4772
4773/*
4774 * Scan the inodes looking for inodes that contain duplicate blocks.
4775 */
4776struct process_block_struct_1b {
4777 e2fsck_t ctx;
4778 ext2_ino_t ino;
4779 int dup_blocks;
4780 struct ext2_inode *inode;
4781 struct problem_context *pctx;
4782};
4783
4784static void pass1b(e2fsck_t ctx, char *block_buf)
4785{
4786 ext2_filsys fs = ctx->fs;
4787 ext2_ino_t ino;
4788 struct ext2_inode inode;
4789 ext2_inode_scan scan;
4790 struct process_block_struct_1b pb;
4791 struct problem_context pctx;
4792
4793 clear_problem_context(&pctx);
4794
4795 if (!(ctx->options & E2F_OPT_PREEN))
4796 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
4797 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4798 &scan);
4799 if (pctx.errcode) {
4800 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4801 ctx->flags |= E2F_FLAG_ABORT;
4802 return;
4803 }
4804 ctx->stashed_inode = &inode;
4805 pb.ctx = ctx;
4806 pb.pctx = &pctx;
4807 pctx.str = "pass1b";
4808 while (1) {
4809 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
4810 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
4811 continue;
4812 if (pctx.errcode) {
4813 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4814 ctx->flags |= E2F_FLAG_ABORT;
4815 return;
4816 }
4817 if (!ino)
4818 break;
4819 pctx.ino = ctx->stashed_ino = ino;
4820 if ((ino != EXT2_BAD_INO) &&
4821 !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
4822 continue;
4823
4824 pb.ino = ino;
4825 pb.dup_blocks = 0;
4826 pb.inode = &inode;
4827
4828 if (ext2fs_inode_has_valid_blocks(&inode) ||
4829 (ino == EXT2_BAD_INO))
4830 pctx.errcode = ext2fs_block_iterate2(fs, ino,
4831 0, block_buf, process_pass1b_block, &pb);
4832 if (inode.i_file_acl)
4833 process_pass1b_block(fs, &inode.i_file_acl,
4834 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
4835 if (pb.dup_blocks) {
4836 end_problem_latch(ctx, PR_LATCH_DBLOCK);
4837 if (ino >= EXT2_FIRST_INODE(fs->super) ||
4838 ino == EXT2_ROOT_INO)
4839 dup_inode_count++;
4840 }
4841 if (pctx.errcode)
4842 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
4843 }
4844 ext2fs_close_inode_scan(scan);
4845 e2fsck_use_inode_shortcuts(ctx, 0);
4846}
4847
4848static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
4849 blk_t *block_nr,
4850 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
4851 blk_t ref_blk FSCK_ATTR((unused)),
4852 int ref_offset FSCK_ATTR((unused)),
4853 void *priv_data)
4854{
4855 struct process_block_struct_1b *p;
4856 e2fsck_t ctx;
4857
4858 if (HOLE_BLKADDR(*block_nr))
4859 return 0;
4860 p = (struct process_block_struct_1b *) priv_data;
4861 ctx = p->ctx;
4862
4863 if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
4864 return 0;
4865
4866 /* OK, this is a duplicate block */
4867 if (p->ino != EXT2_BAD_INO) {
4868 p->pctx->blk = *block_nr;
4869 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
4870 }
4871 p->dup_blocks++;
4872 ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
4873
4874 add_dupe(ctx, p->ino, *block_nr, p->inode);
4875
4876 return 0;
4877}
4878
4879/*
4880 * Pass 1c: Scan directories for inodes with duplicate blocks. This
4881 * is used so that we can print pathnames when prompting the user for
4882 * what to do.
4883 */
4884struct search_dir_struct {
4885 int count;
4886 ext2_ino_t first_inode;
4887 ext2_ino_t max_inode;
4888};
4889
4890static int search_dirent_proc(ext2_ino_t dir, int entry,
4891 struct ext2_dir_entry *dirent,
4892 int offset FSCK_ATTR((unused)),
4893 int blocksize FSCK_ATTR((unused)),
4894 char *buf FSCK_ATTR((unused)),
4895 void *priv_data)
4896{
4897 struct search_dir_struct *sd;
4898 struct dup_inode *p;
4899 dnode_t *n;
4900
4901 sd = (struct search_dir_struct *) priv_data;
4902
4903 if (dirent->inode > sd->max_inode)
4904 /* Should abort this inode, but not everything */
4905 return 0;
4906
4907 if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
4908 !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
4909 return 0;
4910
4911 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
4912 if (!n)
4913 return 0;
4914 p = (struct dup_inode *) dnode_get(n);
4915 p->dir = dir;
4916 sd->count--;
4917
4918 return sd->count ? 0 : DIRENT_ABORT;
4919}
4920
4921
4922static void pass1c(e2fsck_t ctx, char *block_buf)
4923{
4924 ext2_filsys fs = ctx->fs;
4925 struct search_dir_struct sd;
4926 struct problem_context pctx;
4927
4928 clear_problem_context(&pctx);
4929
4930 if (!(ctx->options & E2F_OPT_PREEN))
4931 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
4932
4933 /*
4934 * Search through all directories to translate inodes to names
4935 * (by searching for the containing directory for that inode.)
4936 */
4937 sd.count = dup_inode_count;
4938 sd.first_inode = EXT2_FIRST_INODE(fs->super);
4939 sd.max_inode = fs->super->s_inodes_count;
4940 ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
4941 search_dirent_proc, &sd);
4942}
4943
4944static void pass1d(e2fsck_t ctx, char *block_buf)
4945{
4946 ext2_filsys fs = ctx->fs;
4947 struct dup_inode *p, *t;
4948 struct dup_block *q;
4949 ext2_ino_t *shared, ino;
4950 int shared_len;
4951 int i;
4952 int file_ok;
4953 int meta_data = 0;
4954 struct problem_context pctx;
4955 dnode_t *n, *m;
4956 struct block_el *s;
4957 struct inode_el *r;
4958
4959 clear_problem_context(&pctx);
4960
4961 if (!(ctx->options & E2F_OPT_PREEN))
4962 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
4963 e2fsck_read_bitmaps(ctx);
4964
4965 pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
4966 fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
4967 shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
4968 sizeof(ext2_ino_t) * dict_count(&ino_dict),
4969 "Shared inode list");
4970 for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
4971 p = (struct dup_inode *) dnode_get(n);
4972 shared_len = 0;
4973 file_ok = 1;
4974 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
4975 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
4976 continue;
4977
4978 /*
4979 * Find all of the inodes which share blocks with this
4980 * one. First we find all of the duplicate blocks
4981 * belonging to this inode, and then search each block
4982 * get the list of inodes, and merge them together.
4983 */
4984 for (s = p->block_list; s; s = s->next) {
4985 m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
4986 if (!m)
4987 continue; /* Should never happen... */
4988 q = (struct dup_block *) dnode_get(m);
4989 if (q->num_bad > 1)
4990 file_ok = 0;
4991 if (check_if_fs_block(ctx, s->block)) {
4992 file_ok = 0;
4993 meta_data = 1;
4994 }
4995
4996 /*
4997 * Add all inodes used by this block to the
4998 * shared[] --- which is a unique list, so
4999 * if an inode is already in shared[], don't
5000 * add it again.
5001 */
5002 for (r = q->inode_list; r; r = r->next) {
5003 if (r->inode == ino)
5004 continue;
5005 for (i = 0; i < shared_len; i++)
5006 if (shared[i] == r->inode)
5007 break;
5008 if (i == shared_len) {
5009 shared[shared_len++] = r->inode;
5010 }
5011 }
5012 }
5013
5014 /*
5015 * Report the inode that we are working on
5016 */
5017 pctx.inode = &p->inode;
5018 pctx.ino = ino;
5019 pctx.dir = p->dir;
5020 pctx.blkcount = p->num_dupblocks;
5021 pctx.num = meta_data ? shared_len+1 : shared_len;
5022 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
5023 pctx.blkcount = 0;
5024 pctx.num = 0;
5025
5026 if (meta_data)
5027 fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
5028
5029 for (i = 0; i < shared_len; i++) {
5030 m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
5031 if (!m)
5032 continue; /* should never happen */
5033 t = (struct dup_inode *) dnode_get(m);
5034 /*
5035 * Report the inode that we are sharing with
5036 */
5037 pctx.inode = &t->inode;
5038 pctx.ino = shared[i];
5039 pctx.dir = t->dir;
5040 fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
5041 }
5042 if (file_ok) {
5043 fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
5044 continue;
5045 }
5046 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
5047 pctx.errcode = clone_file(ctx, ino, p, block_buf);
5048 if (pctx.errcode)
5049 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
5050 else
5051 continue;
5052 }
5053 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
5054 delete_file(ctx, ino, p, block_buf);
5055 else
5056 ext2fs_unmark_valid(fs);
5057 }
5058 ext2fs_free_mem(&shared);
5059}
5060
5061/*
5062 * Drop the refcount on the dup_block structure, and clear the entry
5063 * in the block_dup_map if appropriate.
5064 */
5065static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
5066{
5067 p->num_bad--;
5068 if (p->num_bad <= 0 ||
5069 (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
5070 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
5071}
5072
5073static int delete_file_block(ext2_filsys fs,
5074 blk_t *block_nr,
5075 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
5076 blk_t ref_block FSCK_ATTR((unused)),
5077 int ref_offset FSCK_ATTR((unused)),
5078 void *priv_data)
5079{
5080 struct process_block_struct_1b *pb;
5081 struct dup_block *p;
5082 dnode_t *n;
5083 e2fsck_t ctx;
5084
5085 pb = (struct process_block_struct_1b *) priv_data;
5086 ctx = pb->ctx;
5087
5088 if (HOLE_BLKADDR(*block_nr))
5089 return 0;
5090
5091 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5092 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5093 if (n) {
5094 p = (struct dup_block *) dnode_get(n);
5095 decrement_badcount(ctx, *block_nr, p);
5096 } else
5097 bb_error_msg(_("internal error; can't find dup_blk for %d"),
5098 *block_nr);
5099 } else {
5100 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
5101 ext2fs_block_alloc_stats(fs, *block_nr, -1);
5102 }
5103
5104 return 0;
5105}
5106
5107static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5108 struct dup_inode *dp, char* block_buf)
5109{
5110 ext2_filsys fs = ctx->fs;
5111 struct process_block_struct_1b pb;
5112 struct ext2_inode inode;
5113 struct problem_context pctx;
5114 unsigned int count;
5115
5116 clear_problem_context(&pctx);
5117 pctx.ino = pb.ino = ino;
5118 pb.dup_blocks = dp->num_dupblocks;
5119 pb.ctx = ctx;
5120 pctx.str = "delete_file";
5121
5122 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5123 if (ext2fs_inode_has_valid_blocks(&inode))
5124 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5125 delete_file_block, &pb);
5126 if (pctx.errcode)
5127 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5128 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5129 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5130 if (ctx->inode_bad_map)
5131 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
5132 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
5133
5134 /* Inode may have changed by block_iterate, so reread it */
5135 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5136 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00005137 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00005138 if (inode.i_file_acl &&
5139 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
5140 count = 1;
5141 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
5142 block_buf, -1, &count);
5143 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
5144 pctx.errcode = 0;
5145 count = 1;
5146 }
5147 if (pctx.errcode) {
5148 pctx.blk = inode.i_file_acl;
5149 fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
5150 }
5151 /*
5152 * If the count is zero, then arrange to have the
5153 * block deleted. If the block is in the block_dup_map,
5154 * also call delete_file_block since it will take care
5155 * of keeping the accounting straight.
5156 */
5157 if ((count == 0) ||
5158 ext2fs_test_block_bitmap(ctx->block_dup_map,
5159 inode.i_file_acl))
5160 delete_file_block(fs, &inode.i_file_acl,
5161 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
5162 }
5163 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
5164}
5165
5166struct clone_struct {
5167 errcode_t errcode;
5168 ext2_ino_t dir;
5169 char *buf;
5170 e2fsck_t ctx;
5171};
5172
5173static int clone_file_block(ext2_filsys fs,
5174 blk_t *block_nr,
5175 e2_blkcnt_t blockcnt,
5176 blk_t ref_block FSCK_ATTR((unused)),
5177 int ref_offset FSCK_ATTR((unused)),
5178 void *priv_data)
5179{
5180 struct dup_block *p;
5181 blk_t new_block;
5182 errcode_t retval;
5183 struct clone_struct *cs = (struct clone_struct *) priv_data;
5184 dnode_t *n;
5185 e2fsck_t ctx;
5186
5187 ctx = cs->ctx;
5188
5189 if (HOLE_BLKADDR(*block_nr))
5190 return 0;
5191
5192 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5193 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5194 if (n) {
5195 p = (struct dup_block *) dnode_get(n);
5196 retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
5197 &new_block);
5198 if (retval) {
5199 cs->errcode = retval;
5200 return BLOCK_ABORT;
5201 }
5202 if (cs->dir && (blockcnt >= 0)) {
5203 retval = ext2fs_set_dir_block(fs->dblist,
5204 cs->dir, new_block, blockcnt);
5205 if (retval) {
5206 cs->errcode = retval;
5207 return BLOCK_ABORT;
5208 }
5209 }
5210
5211 retval = io_channel_read_blk(fs->io, *block_nr, 1,
5212 cs->buf);
5213 if (retval) {
5214 cs->errcode = retval;
5215 return BLOCK_ABORT;
5216 }
5217 retval = io_channel_write_blk(fs->io, new_block, 1,
5218 cs->buf);
5219 if (retval) {
5220 cs->errcode = retval;
5221 return BLOCK_ABORT;
5222 }
5223 decrement_badcount(ctx, *block_nr, p);
5224 *block_nr = new_block;
5225 ext2fs_mark_block_bitmap(ctx->block_found_map,
5226 new_block);
5227 ext2fs_mark_block_bitmap(fs->block_map, new_block);
5228 return BLOCK_CHANGED;
5229 } else
5230 bb_error_msg(_("internal error; can't find dup_blk for %d"),
5231 *block_nr);
5232 }
5233 return 0;
5234}
5235
5236static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5237 struct dup_inode *dp, char* block_buf)
5238{
5239 ext2_filsys fs = ctx->fs;
5240 errcode_t retval;
5241 struct clone_struct cs;
5242 struct problem_context pctx;
5243 blk_t blk;
5244 dnode_t *n;
5245 struct inode_el *ino_el;
5246 struct dup_block *db;
5247 struct dup_inode *di;
5248
5249 clear_problem_context(&pctx);
5250 cs.errcode = 0;
5251 cs.dir = 0;
5252 cs.ctx = ctx;
5253 retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
5254 if (retval)
5255 return retval;
5256
5257 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
5258 cs.dir = ino;
5259
5260 pctx.ino = ino;
5261 pctx.str = "clone_file";
5262 if (ext2fs_inode_has_valid_blocks(&dp->inode))
5263 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5264 clone_file_block, &cs);
5265 ext2fs_mark_bb_dirty(fs);
5266 if (pctx.errcode) {
5267 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5268 retval = pctx.errcode;
5269 goto errout;
5270 }
5271 if (cs.errcode) {
5272 bb_error_msg(_("returned from clone_file_block"));
5273 retval = cs.errcode;
5274 goto errout;
5275 }
5276 /* The inode may have changed on disk, so we have to re-read it */
5277 e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
5278 blk = dp->inode.i_file_acl;
5279 if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
5280 BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
5281 BLOCK_CHANGED)) {
5282 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
5283 /*
5284 * If we cloned the EA block, find all other inodes
5285 * which refered to that EA block, and modify
5286 * them to point to the new EA block.
5287 */
5288 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5289 db = (struct dup_block *) dnode_get(n);
5290 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
5291 if (ino_el->inode == ino)
5292 continue;
5293 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
5294 di = (struct dup_inode *) dnode_get(n);
5295 if (di->inode.i_file_acl == blk) {
5296 di->inode.i_file_acl = dp->inode.i_file_acl;
5297 e2fsck_write_inode(ctx, ino_el->inode,
5298 &di->inode, "clone file EA");
5299 decrement_badcount(ctx, blk, db);
5300 }
5301 }
5302 }
5303 retval = 0;
5304errout:
5305 ext2fs_free_mem(&cs.buf);
5306 return retval;
5307}
5308
5309/*
5310 * This routine returns 1 if a block overlaps with one of the superblocks,
5311 * group descriptors, inode bitmaps, or block bitmaps.
5312 */
5313static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
5314{
5315 ext2_filsys fs = ctx->fs;
5316 blk_t block;
5317 dgrp_t i;
5318
5319 block = fs->super->s_first_data_block;
5320 for (i = 0; i < fs->group_desc_count; i++) {
5321
5322 /* Check superblocks/block group descriptros */
5323 if (ext2fs_bg_has_super(fs, i)) {
5324 if (test_block >= block &&
5325 (test_block <= block + fs->desc_blocks))
5326 return 1;
5327 }
5328
5329 /* Check the inode table */
5330 if ((fs->group_desc[i].bg_inode_table) &&
5331 (test_block >= fs->group_desc[i].bg_inode_table) &&
5332 (test_block < (fs->group_desc[i].bg_inode_table +
5333 fs->inode_blocks_per_group)))
5334 return 1;
5335
5336 /* Check the bitmap blocks */
5337 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
5338 (test_block == fs->group_desc[i].bg_inode_bitmap))
5339 return 1;
5340
5341 block += fs->super->s_blocks_per_group;
5342 }
5343 return 0;
5344}
5345/*
5346 * pass2.c --- check directory structure
5347 *
5348 * Pass 2 of e2fsck iterates through all active directory inodes, and
5349 * applies to following tests to each directory entry in the directory
5350 * blocks in the inodes:
5351 *
5352 * - The length of the directory entry (rec_len) should be at
5353 * least 8 bytes, and no more than the remaining space
5354 * left in the directory block.
5355 * - The length of the name in the directory entry (name_len)
5356 * should be less than (rec_len - 8).
5357 * - The inode number in the directory entry should be within
5358 * legal bounds.
5359 * - The inode number should refer to a in-use inode.
5360 * - The first entry should be '.', and its inode should be
5361 * the inode of the directory.
5362 * - The second entry should be '..'.
5363 *
5364 * To minimize disk seek time, the directory blocks are processed in
5365 * sorted order of block numbers.
5366 *
5367 * Pass 2 also collects the following information:
5368 * - The inode numbers of the subdirectories for each directory.
5369 *
5370 * Pass 2 relies on the following information from previous passes:
5371 * - The directory information collected in pass 1.
5372 * - The inode_used_map bitmap
5373 * - The inode_bad_map bitmap
5374 * - The inode_dir_map bitmap
5375 *
5376 * Pass 2 frees the following data structures
5377 * - The inode_bad_map bitmap
5378 * - The inode_reg_map bitmap
5379 */
5380
5381/*
5382 * Keeps track of how many times an inode is referenced.
5383 */
5384static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
5385static int check_dir_block(ext2_filsys fs,
5386 struct ext2_db_entry *dir_blocks_info,
5387 void *priv_data);
5388static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
5389 struct problem_context *pctx);
5390static int update_dir_block(ext2_filsys fs,
5391 blk_t *block_nr,
5392 e2_blkcnt_t blockcnt,
5393 blk_t ref_block,
5394 int ref_offset,
5395 void *priv_data);
5396static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
5397static int htree_depth(struct dx_dir_info *dx_dir,
5398 struct dx_dirblock_info *dx_db);
5399static int special_dir_block_cmp(const void *a, const void *b);
5400
5401struct check_dir_struct {
5402 char *buf;
5403 struct problem_context pctx;
5404 int count, max;
5405 e2fsck_t ctx;
5406};
5407
5408static void e2fsck_pass2(e2fsck_t ctx)
5409{
5410 struct ext2_super_block *sb = ctx->fs->super;
5411 struct problem_context pctx;
5412 ext2_filsys fs = ctx->fs;
5413 char *buf;
5414 struct dir_info *dir;
5415 struct check_dir_struct cd;
5416 struct dx_dir_info *dx_dir;
5417 struct dx_dirblock_info *dx_db, *dx_parent;
5418 int b;
5419 int i, depth;
5420 problem_t code;
5421 int bad_dir;
5422
5423 clear_problem_context(&cd.pctx);
5424
5425 /* Pass 2 */
5426
5427 if (!(ctx->options & E2F_OPT_PREEN))
5428 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
5429
5430 cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
5431 0, ctx->inode_link_info,
5432 &ctx->inode_count);
5433 if (cd.pctx.errcode) {
5434 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
5435 ctx->flags |= E2F_FLAG_ABORT;
5436 return;
5437 }
5438 buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
5439 "directory scan buffer");
5440
5441 /*
5442 * Set up the parent pointer for the root directory, if
5443 * present. (If the root directory is not present, we will
5444 * create it in pass 3.)
5445 */
5446 dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
5447 if (dir)
5448 dir->parent = EXT2_ROOT_INO;
5449
5450 cd.buf = buf;
5451 cd.ctx = ctx;
5452 cd.count = 1;
5453 cd.max = ext2fs_dblist_count(fs->dblist);
5454
5455 if (ctx->progress)
5456 (void) (ctx->progress)(ctx, 2, 0, cd.max);
5457
5458 if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
5459 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
5460
5461 cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
5462 &cd);
5463 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5464 return;
5465 if (cd.pctx.errcode) {
5466 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
5467 ctx->flags |= E2F_FLAG_ABORT;
5468 return;
5469 }
5470
5471#ifdef ENABLE_HTREE
5472 for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
5473 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5474 return;
5475 if (dx_dir->numblocks == 0)
5476 continue;
5477 clear_problem_context(&pctx);
5478 bad_dir = 0;
5479 pctx.dir = dx_dir->ino;
5480 dx_db = dx_dir->dx_block;
5481 if (dx_db->flags & DX_FLAG_REFERENCED)
5482 dx_db->flags |= DX_FLAG_DUP_REF;
5483 else
5484 dx_db->flags |= DX_FLAG_REFERENCED;
5485 /*
5486 * Find all of the first and last leaf blocks, and
5487 * update their parent's min and max hash values
5488 */
5489 for (b=0, dx_db = dx_dir->dx_block;
5490 b < dx_dir->numblocks;
5491 b++, dx_db++) {
5492 if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
5493 !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
5494 continue;
5495 dx_parent = &dx_dir->dx_block[dx_db->parent];
5496 /*
5497 * XXX Make sure dx_parent->min_hash > dx_db->min_hash
5498 */
5499 if (dx_db->flags & DX_FLAG_FIRST)
5500 dx_parent->min_hash = dx_db->min_hash;
5501 /*
5502 * XXX Make sure dx_parent->max_hash < dx_db->max_hash
5503 */
5504 if (dx_db->flags & DX_FLAG_LAST)
5505 dx_parent->max_hash = dx_db->max_hash;
5506 }
5507
5508 for (b=0, dx_db = dx_dir->dx_block;
5509 b < dx_dir->numblocks;
5510 b++, dx_db++) {
5511 pctx.blkcount = b;
5512 pctx.group = dx_db->parent;
5513 code = 0;
5514 if (!(dx_db->flags & DX_FLAG_FIRST) &&
5515 (dx_db->min_hash < dx_db->node_min_hash)) {
5516 pctx.blk = dx_db->min_hash;
5517 pctx.blk2 = dx_db->node_min_hash;
5518 code = PR_2_HTREE_MIN_HASH;
5519 fix_problem(ctx, code, &pctx);
5520 bad_dir++;
5521 }
5522 if (dx_db->type == DX_DIRBLOCK_LEAF) {
5523 depth = htree_depth(dx_dir, dx_db);
5524 if (depth != dx_dir->depth) {
5525 code = PR_2_HTREE_BAD_DEPTH;
5526 fix_problem(ctx, code, &pctx);
5527 bad_dir++;
5528 }
5529 }
5530 /*
5531 * This test doesn't apply for the root block
5532 * at block #0
5533 */
5534 if (b &&
5535 (dx_db->max_hash > dx_db->node_max_hash)) {
5536 pctx.blk = dx_db->max_hash;
5537 pctx.blk2 = dx_db->node_max_hash;
5538 code = PR_2_HTREE_MAX_HASH;
5539 fix_problem(ctx, code, &pctx);
5540 bad_dir++;
5541 }
5542 if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
5543 code = PR_2_HTREE_NOTREF;
5544 fix_problem(ctx, code, &pctx);
5545 bad_dir++;
5546 } else if (dx_db->flags & DX_FLAG_DUP_REF) {
5547 code = PR_2_HTREE_DUPREF;
5548 fix_problem(ctx, code, &pctx);
5549 bad_dir++;
5550 }
5551 if (code == 0)
5552 continue;
5553 }
5554 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
5555 clear_htree(ctx, dx_dir->ino);
5556 dx_dir->numblocks = 0;
5557 }
5558 }
5559#endif
5560 ext2fs_free_mem(&buf);
5561 ext2fs_free_dblist(fs->dblist);
5562
5563 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
5564 ctx->inode_bad_map = 0;
5565 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
5566 ctx->inode_reg_map = 0;
5567
5568 clear_problem_context(&pctx);
5569 if (ctx->large_files) {
5570 if (!(sb->s_feature_ro_compat &
5571 EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
5572 fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
5573 sb->s_feature_ro_compat |=
5574 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5575 ext2fs_mark_super_dirty(fs);
5576 }
5577 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
5578 fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
5579 ext2fs_update_dynamic_rev(fs);
5580 ext2fs_mark_super_dirty(fs);
5581 }
5582 } else if (!ctx->large_files &&
5583 (sb->s_feature_ro_compat &
5584 EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
5585 if (fs->flags & EXT2_FLAG_RW) {
5586 sb->s_feature_ro_compat &=
5587 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5588 ext2fs_mark_super_dirty(fs);
5589 }
5590 }
5591
5592}
5593
5594#define MAX_DEPTH 32000
5595static int htree_depth(struct dx_dir_info *dx_dir,
5596 struct dx_dirblock_info *dx_db)
5597{
5598 int depth = 0;
5599
5600 while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
5601 dx_db = &dx_dir->dx_block[dx_db->parent];
5602 depth++;
5603 }
5604 return depth;
5605}
5606
5607static int dict_de_cmp(const void *a, const void *b)
5608{
5609 const struct ext2_dir_entry *de_a, *de_b;
5610 int a_len, b_len;
5611
5612 de_a = (const struct ext2_dir_entry *) a;
5613 a_len = de_a->name_len & 0xFF;
5614 de_b = (const struct ext2_dir_entry *) b;
5615 b_len = de_b->name_len & 0xFF;
5616
5617 if (a_len != b_len)
5618 return (a_len - b_len);
5619
5620 return strncmp(de_a->name, de_b->name, a_len);
5621}
5622
5623/*
5624 * This is special sort function that makes sure that directory blocks
5625 * with a dirblock of zero are sorted to the beginning of the list.
5626 * This guarantees that the root node of the htree directories are
5627 * processed first, so we know what hash version to use.
5628 */
5629static int special_dir_block_cmp(const void *a, const void *b)
5630{
5631 const struct ext2_db_entry *db_a =
5632 (const struct ext2_db_entry *) a;
5633 const struct ext2_db_entry *db_b =
5634 (const struct ext2_db_entry *) b;
5635
5636 if (db_a->blockcnt && !db_b->blockcnt)
5637 return 1;
5638
5639 if (!db_a->blockcnt && db_b->blockcnt)
5640 return -1;
5641
5642 if (db_a->blk != db_b->blk)
5643 return (int) (db_a->blk - db_b->blk);
5644
5645 if (db_a->ino != db_b->ino)
5646 return (int) (db_a->ino - db_b->ino);
5647
5648 return (int) (db_a->blockcnt - db_b->blockcnt);
5649}
5650
5651
5652/*
5653 * Make sure the first entry in the directory is '.', and that the
5654 * directory entry is sane.
5655 */
5656static int check_dot(e2fsck_t ctx,
5657 struct ext2_dir_entry *dirent,
5658 ext2_ino_t ino, struct problem_context *pctx)
5659{
5660 struct ext2_dir_entry *nextdir;
5661 int status = 0;
5662 int created = 0;
5663 int new_len;
5664 int problem = 0;
5665
5666 if (!dirent->inode)
5667 problem = PR_2_MISSING_DOT;
5668 else if (((dirent->name_len & 0xFF) != 1) ||
5669 (dirent->name[0] != '.'))
5670 problem = PR_2_1ST_NOT_DOT;
5671 else if (dirent->name[1] != '\0')
5672 problem = PR_2_DOT_NULL_TERM;
5673
5674 if (problem) {
5675 if (fix_problem(ctx, problem, pctx)) {
5676 if (dirent->rec_len < 12)
5677 dirent->rec_len = 12;
5678 dirent->inode = ino;
5679 dirent->name_len = 1;
5680 dirent->name[0] = '.';
5681 dirent->name[1] = '\0';
5682 status = 1;
5683 created = 1;
5684 }
5685 }
5686 if (dirent->inode != ino) {
5687 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
5688 dirent->inode = ino;
5689 status = 1;
5690 }
5691 }
5692 if (dirent->rec_len > 12) {
5693 new_len = dirent->rec_len - 12;
5694 if (new_len > 12) {
5695 if (created ||
5696 fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
5697 nextdir = (struct ext2_dir_entry *)
5698 ((char *) dirent + 12);
5699 dirent->rec_len = 12;
5700 nextdir->rec_len = new_len;
5701 nextdir->inode = 0;
5702 nextdir->name_len = 0;
5703 status = 1;
5704 }
5705 }
5706 }
5707 return status;
5708}
5709
5710/*
5711 * Make sure the second entry in the directory is '..', and that the
5712 * directory entry is sane. We do not check the inode number of '..'
5713 * here; this gets done in pass 3.
5714 */
5715static int check_dotdot(e2fsck_t ctx,
5716 struct ext2_dir_entry *dirent,
5717 struct dir_info *dir, struct problem_context *pctx)
5718{
5719 int problem = 0;
5720
5721 if (!dirent->inode)
5722 problem = PR_2_MISSING_DOT_DOT;
5723 else if (((dirent->name_len & 0xFF) != 2) ||
5724 (dirent->name[0] != '.') ||
5725 (dirent->name[1] != '.'))
5726 problem = PR_2_2ND_NOT_DOT_DOT;
5727 else if (dirent->name[2] != '\0')
5728 problem = PR_2_DOT_DOT_NULL_TERM;
5729
5730 if (problem) {
5731 if (fix_problem(ctx, problem, pctx)) {
5732 if (dirent->rec_len < 12)
5733 dirent->rec_len = 12;
5734 /*
5735 * Note: we don't have the parent inode just
5736 * yet, so we will fill it in with the root
5737 * inode. This will get fixed in pass 3.
5738 */
5739 dirent->inode = EXT2_ROOT_INO;
5740 dirent->name_len = 2;
5741 dirent->name[0] = '.';
5742 dirent->name[1] = '.';
5743 dirent->name[2] = '\0';
5744 return 1;
5745 }
5746 return 0;
5747 }
5748 dir->dotdot = dirent->inode;
5749 return 0;
5750}
5751
5752/*
5753 * Check to make sure a directory entry doesn't contain any illegal
5754 * characters.
5755 */
5756static int check_name(e2fsck_t ctx,
5757 struct ext2_dir_entry *dirent,
5758 struct problem_context *pctx)
5759{
5760 int i;
5761 int fixup = -1;
5762 int ret = 0;
5763
5764 for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
5765 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
5766 if (fixup < 0) {
5767 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
5768 }
5769 if (fixup) {
5770 dirent->name[i] = '.';
5771 ret = 1;
5772 }
5773 }
5774 }
5775 return ret;
5776}
5777
5778/*
5779 * Check the directory filetype (if present)
5780 */
5781
5782/*
5783 * Given a mode, return the ext2 file type
5784 */
5785static int ext2_file_type(unsigned int mode)
5786{
5787 if (LINUX_S_ISREG(mode))
5788 return EXT2_FT_REG_FILE;
5789
5790 if (LINUX_S_ISDIR(mode))
5791 return EXT2_FT_DIR;
5792
5793 if (LINUX_S_ISCHR(mode))
5794 return EXT2_FT_CHRDEV;
5795
5796 if (LINUX_S_ISBLK(mode))
5797 return EXT2_FT_BLKDEV;
5798
5799 if (LINUX_S_ISLNK(mode))
5800 return EXT2_FT_SYMLINK;
5801
5802 if (LINUX_S_ISFIFO(mode))
5803 return EXT2_FT_FIFO;
5804
5805 if (LINUX_S_ISSOCK(mode))
5806 return EXT2_FT_SOCK;
5807
5808 return 0;
5809}
5810
5811static int check_filetype(e2fsck_t ctx,
5812 struct ext2_dir_entry *dirent,
5813 struct problem_context *pctx)
5814{
5815 int filetype = dirent->name_len >> 8;
5816 int should_be = EXT2_FT_UNKNOWN;
5817 struct ext2_inode inode;
5818
5819 if (!(ctx->fs->super->s_feature_incompat &
5820 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
5821 if (filetype == 0 ||
5822 !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
5823 return 0;
5824 dirent->name_len = dirent->name_len & 0xFF;
5825 return 1;
5826 }
5827
5828 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
5829 should_be = EXT2_FT_DIR;
5830 } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
5831 dirent->inode)) {
5832 should_be = EXT2_FT_REG_FILE;
5833 } else if (ctx->inode_bad_map &&
5834 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
5835 dirent->inode))
5836 should_be = 0;
5837 else {
5838 e2fsck_read_inode(ctx, dirent->inode, &inode,
5839 "check_filetype");
5840 should_be = ext2_file_type(inode.i_mode);
5841 }
5842 if (filetype == should_be)
5843 return 0;
5844 pctx->num = should_be;
5845
5846 if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
5847 pctx) == 0)
5848 return 0;
5849
5850 dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
5851 return 1;
5852}
5853
5854#ifdef ENABLE_HTREE
5855static void parse_int_node(ext2_filsys fs,
5856 struct ext2_db_entry *db,
5857 struct check_dir_struct *cd,
5858 struct dx_dir_info *dx_dir,
5859 char *block_buf)
5860{
5861 struct ext2_dx_root_info *root;
5862 struct ext2_dx_entry *ent;
5863 struct ext2_dx_countlimit *limit;
5864 struct dx_dirblock_info *dx_db;
5865 int i, expect_limit, count;
5866 blk_t blk;
5867 ext2_dirhash_t min_hash = 0xffffffff;
5868 ext2_dirhash_t max_hash = 0;
5869 ext2_dirhash_t hash = 0, prev_hash;
5870
5871 if (db->blockcnt == 0) {
5872 root = (struct ext2_dx_root_info *) (block_buf + 24);
5873 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5874 } else {
5875 ent = (struct ext2_dx_entry *) (block_buf+8);
5876 }
5877 limit = (struct ext2_dx_countlimit *) ent;
5878
5879 count = ext2fs_le16_to_cpu(limit->count);
5880 expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
5881 sizeof(struct ext2_dx_entry);
5882 if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5883 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
5884 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
5885 goto clear_and_exit;
5886 }
5887 if (count > expect_limit) {
5888 cd->pctx.num = count;
5889 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
5890 goto clear_and_exit;
5891 count = expect_limit;
5892 }
5893
5894 for (i=0; i < count; i++) {
5895 prev_hash = hash;
5896 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5897 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5898 /* Check to make sure the block is valid */
5899 if (blk > (blk_t) dx_dir->numblocks) {
5900 cd->pctx.blk = blk;
5901 if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
5902 &cd->pctx))
5903 goto clear_and_exit;
5904 }
5905 if (hash < prev_hash &&
5906 fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
5907 goto clear_and_exit;
5908 dx_db = &dx_dir->dx_block[blk];
5909 if (dx_db->flags & DX_FLAG_REFERENCED) {
5910 dx_db->flags |= DX_FLAG_DUP_REF;
5911 } else {
5912 dx_db->flags |= DX_FLAG_REFERENCED;
5913 dx_db->parent = db->blockcnt;
5914 }
5915 if (hash < min_hash)
5916 min_hash = hash;
5917 if (hash > max_hash)
5918 max_hash = hash;
5919 dx_db->node_min_hash = hash;
5920 if ((i+1) < count)
5921 dx_db->node_max_hash =
5922 ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
5923 else {
5924 dx_db->node_max_hash = 0xfffffffe;
5925 dx_db->flags |= DX_FLAG_LAST;
5926 }
5927 if (i == 0)
5928 dx_db->flags |= DX_FLAG_FIRST;
5929 }
5930 dx_db = &dx_dir->dx_block[db->blockcnt];
5931 dx_db->min_hash = min_hash;
5932 dx_db->max_hash = max_hash;
5933 return;
5934
5935clear_and_exit:
5936 clear_htree(cd->ctx, cd->pctx.ino);
5937 dx_dir->numblocks = 0;
5938}
5939#endif /* ENABLE_HTREE */
5940
5941/*
5942 * Given a busted directory, try to salvage it somehow.
5943 *
5944 */
5945static void salvage_directory(ext2_filsys fs,
5946 struct ext2_dir_entry *dirent,
5947 struct ext2_dir_entry *prev,
5948 unsigned int *offset)
5949{
5950 char *cp = (char *) dirent;
5951 int left = fs->blocksize - *offset - dirent->rec_len;
5952 int name_len = dirent->name_len & 0xFF;
5953
5954 /*
5955 * Special case of directory entry of size 8: copy what's left
5956 * of the directory block up to cover up the invalid hole.
5957 */
5958 if ((left >= 12) && (dirent->rec_len == 8)) {
5959 memmove(cp, cp+8, left);
5960 memset(cp + left, 0, 8);
5961 return;
5962 }
5963 /*
5964 * If the directory entry overruns the end of the directory
5965 * block, and the name is small enough to fit, then adjust the
5966 * record length.
5967 */
5968 if ((left < 0) &&
5969 (name_len + 8 <= dirent->rec_len + left) &&
5970 dirent->inode <= fs->super->s_inodes_count &&
5971 strnlen(dirent->name, name_len) == name_len) {
5972 dirent->rec_len += left;
5973 return;
5974 }
5975 /*
5976 * If the directory entry is a multiple of four, so it is
5977 * valid, let the previous directory entry absorb the invalid
5978 * one.
5979 */
5980 if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
5981 prev->rec_len += dirent->rec_len;
5982 *offset += dirent->rec_len;
5983 return;
5984 }
5985 /*
5986 * Default salvage method --- kill all of the directory
5987 * entries for the rest of the block. We will either try to
5988 * absorb it into the previous directory entry, or create a
5989 * new empty directory entry the rest of the directory block.
5990 */
5991 if (prev) {
5992 prev->rec_len += fs->blocksize - *offset;
5993 *offset = fs->blocksize;
5994 } else {
5995 dirent->rec_len = fs->blocksize - *offset;
5996 dirent->name_len = 0;
5997 dirent->inode = 0;
5998 }
5999}
6000
6001static int check_dir_block(ext2_filsys fs,
6002 struct ext2_db_entry *db,
6003 void *priv_data)
6004{
6005 struct dir_info *subdir, *dir;
6006 struct dx_dir_info *dx_dir;
6007#ifdef ENABLE_HTREE
Denys Vlasenko4b1100e2010-03-05 14:10:54 +01006008 struct dx_dirblock_info *dx_db = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00006009#endif /* ENABLE_HTREE */
6010 struct ext2_dir_entry *dirent, *prev;
6011 ext2_dirhash_t hash;
6012 unsigned int offset = 0;
6013 int dir_modified = 0;
6014 int dot_state;
6015 blk_t block_nr = db->blk;
6016 ext2_ino_t ino = db->ino;
6017 __u16 links;
6018 struct check_dir_struct *cd;
6019 char *buf;
6020 e2fsck_t ctx;
6021 int problem;
6022 struct ext2_dx_root_info *root;
6023 struct ext2_dx_countlimit *limit;
6024 static dict_t de_dict;
6025 struct problem_context pctx;
6026 int dups_found = 0;
6027
6028 cd = (struct check_dir_struct *) priv_data;
6029 buf = cd->buf;
6030 ctx = cd->ctx;
6031
6032 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6033 return DIRENT_ABORT;
6034
6035 if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
6036 return DIRENT_ABORT;
6037
6038 /*
6039 * Make sure the inode is still in use (could have been
6040 * deleted in the duplicate/bad blocks pass.
6041 */
6042 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
6043 return 0;
6044
6045 cd->pctx.ino = ino;
6046 cd->pctx.blk = block_nr;
6047 cd->pctx.blkcount = db->blockcnt;
6048 cd->pctx.ino2 = 0;
6049 cd->pctx.dirent = 0;
6050 cd->pctx.num = 0;
6051
6052 if (db->blk == 0) {
6053 if (allocate_dir_block(ctx, db, &cd->pctx))
6054 return 0;
6055 block_nr = db->blk;
6056 }
6057
6058 if (db->blockcnt)
6059 dot_state = 2;
6060 else
6061 dot_state = 0;
6062
6063 if (ctx->dirs_to_hash &&
6064 ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
6065 dups_found++;
6066
6067 cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
6068 if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
6069 cd->pctx.errcode = 0; /* We'll handle this ourselves */
6070 if (cd->pctx.errcode) {
6071 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
6072 ctx->flags |= E2F_FLAG_ABORT;
6073 return DIRENT_ABORT;
6074 }
6075 memset(buf, 0, fs->blocksize);
6076 }
6077#ifdef ENABLE_HTREE
6078 dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
6079 if (dx_dir && dx_dir->numblocks) {
6080 if (db->blockcnt >= dx_dir->numblocks) {
6081 printf("XXX should never happen!!!\n");
6082 abort();
6083 }
6084 dx_db = &dx_dir->dx_block[db->blockcnt];
6085 dx_db->type = DX_DIRBLOCK_LEAF;
6086 dx_db->phys = block_nr;
6087 dx_db->min_hash = ~0;
6088 dx_db->max_hash = 0;
6089
6090 dirent = (struct ext2_dir_entry *) buf;
6091 limit = (struct ext2_dx_countlimit *) (buf+8);
6092 if (db->blockcnt == 0) {
6093 root = (struct ext2_dx_root_info *) (buf + 24);
6094 dx_db->type = DX_DIRBLOCK_ROOT;
6095 dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
6096 if ((root->reserved_zero ||
6097 root->info_length < 8 ||
6098 root->indirect_levels > 1) &&
6099 fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
6100 clear_htree(ctx, ino);
6101 dx_dir->numblocks = 0;
6102 dx_db = 0;
6103 }
6104 dx_dir->hashversion = root->hash_version;
6105 dx_dir->depth = root->indirect_levels + 1;
6106 } else if ((dirent->inode == 0) &&
6107 (dirent->rec_len == fs->blocksize) &&
6108 (dirent->name_len == 0) &&
6109 (ext2fs_le16_to_cpu(limit->limit) ==
6110 ((fs->blocksize-8) /
6111 sizeof(struct ext2_dx_entry))))
6112 dx_db->type = DX_DIRBLOCK_NODE;
6113 }
6114#endif /* ENABLE_HTREE */
6115
6116 dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
6117 prev = 0;
6118 do {
6119 problem = 0;
6120 dirent = (struct ext2_dir_entry *) (buf + offset);
6121 cd->pctx.dirent = dirent;
6122 cd->pctx.num = offset;
6123 if (((offset + dirent->rec_len) > fs->blocksize) ||
6124 (dirent->rec_len < 12) ||
6125 ((dirent->rec_len % 4) != 0) ||
6126 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
6127 if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
6128 salvage_directory(fs, dirent, prev, &offset);
6129 dir_modified++;
6130 continue;
6131 } else
6132 goto abort_free_dict;
6133 }
6134 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
6135 if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
6136 dirent->name_len = EXT2_NAME_LEN;
6137 dir_modified++;
6138 }
6139 }
6140
6141 if (dot_state == 0) {
6142 if (check_dot(ctx, dirent, ino, &cd->pctx))
6143 dir_modified++;
6144 } else if (dot_state == 1) {
6145 dir = e2fsck_get_dir_info(ctx, ino);
6146 if (!dir) {
6147 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6148 goto abort_free_dict;
6149 }
6150 if (check_dotdot(ctx, dirent, dir, &cd->pctx))
6151 dir_modified++;
6152 } else if (dirent->inode == ino) {
6153 problem = PR_2_LINK_DOT;
6154 if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
6155 dirent->inode = 0;
6156 dir_modified++;
6157 goto next;
6158 }
6159 }
6160 if (!dirent->inode)
6161 goto next;
6162
6163 /*
6164 * Make sure the inode listed is a legal one.
6165 */
6166 if (((dirent->inode != EXT2_ROOT_INO) &&
6167 (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
6168 (dirent->inode > fs->super->s_inodes_count)) {
6169 problem = PR_2_BAD_INO;
6170 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
6171 dirent->inode))) {
6172 /*
6173 * If the inode is unused, offer to clear it.
6174 */
6175 problem = PR_2_UNUSED_INODE;
6176 } else if ((dot_state > 1) &&
6177 ((dirent->name_len & 0xFF) == 1) &&
6178 (dirent->name[0] == '.')) {
6179 /*
6180 * If there's a '.' entry in anything other
6181 * than the first directory entry, it's a
6182 * duplicate entry that should be removed.
6183 */
6184 problem = PR_2_DUP_DOT;
6185 } else if ((dot_state > 1) &&
6186 ((dirent->name_len & 0xFF) == 2) &&
6187 (dirent->name[0] == '.') &&
6188 (dirent->name[1] == '.')) {
6189 /*
6190 * If there's a '..' entry in anything other
6191 * than the second directory entry, it's a
6192 * duplicate entry that should be removed.
6193 */
6194 problem = PR_2_DUP_DOT_DOT;
6195 } else if ((dot_state > 1) &&
6196 (dirent->inode == EXT2_ROOT_INO)) {
6197 /*
6198 * Don't allow links to the root directory.
6199 * We check this specially to make sure we
6200 * catch this error case even if the root
6201 * directory hasn't been created yet.
6202 */
6203 problem = PR_2_LINK_ROOT;
6204 } else if ((dot_state > 1) &&
6205 (dirent->name_len & 0xFF) == 0) {
6206 /*
6207 * Don't allow zero-length directory names.
6208 */
6209 problem = PR_2_NULL_NAME;
6210 }
6211
6212 if (problem) {
6213 if (fix_problem(ctx, problem, &cd->pctx)) {
6214 dirent->inode = 0;
6215 dir_modified++;
6216 goto next;
6217 } else {
6218 ext2fs_unmark_valid(fs);
6219 if (problem == PR_2_BAD_INO)
6220 goto next;
6221 }
6222 }
6223
6224 /*
6225 * If the inode was marked as having bad fields in
6226 * pass1, process it and offer to fix/clear it.
6227 * (We wait until now so that we can display the
6228 * pathname to the user.)
6229 */
6230 if (ctx->inode_bad_map &&
6231 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
6232 dirent->inode)) {
6233 if (e2fsck_process_bad_inode(ctx, ino,
6234 dirent->inode,
6235 buf + fs->blocksize)) {
6236 dirent->inode = 0;
6237 dir_modified++;
6238 goto next;
6239 }
6240 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6241 return DIRENT_ABORT;
6242 }
6243
6244 if (check_name(ctx, dirent, &cd->pctx))
6245 dir_modified++;
6246
6247 if (check_filetype(ctx, dirent, &cd->pctx))
6248 dir_modified++;
6249
6250#ifdef ENABLE_HTREE
6251 if (dx_db) {
6252 ext2fs_dirhash(dx_dir->hashversion, dirent->name,
6253 (dirent->name_len & 0xFF),
6254 fs->super->s_hash_seed, &hash, 0);
6255 if (hash < dx_db->min_hash)
6256 dx_db->min_hash = hash;
6257 if (hash > dx_db->max_hash)
6258 dx_db->max_hash = hash;
6259 }
6260#endif
6261
6262 /*
6263 * If this is a directory, then mark its parent in its
6264 * dir_info structure. If the parent field is already
6265 * filled in, then this directory has more than one
6266 * hard link. We assume the first link is correct,
6267 * and ask the user if he/she wants to clear this one.
6268 */
6269 if ((dot_state > 1) &&
6270 (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6271 dirent->inode))) {
6272 subdir = e2fsck_get_dir_info(ctx, dirent->inode);
6273 if (!subdir) {
6274 cd->pctx.ino = dirent->inode;
6275 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6276 goto abort_free_dict;
6277 }
6278 if (subdir->parent) {
6279 cd->pctx.ino2 = subdir->parent;
6280 if (fix_problem(ctx, PR_2_LINK_DIR,
6281 &cd->pctx)) {
6282 dirent->inode = 0;
6283 dir_modified++;
6284 goto next;
6285 }
6286 cd->pctx.ino2 = 0;
6287 } else
6288 subdir->parent = ino;
6289 }
6290
6291 if (dups_found) {
6292 ;
6293 } else if (dict_lookup(&de_dict, dirent)) {
6294 clear_problem_context(&pctx);
6295 pctx.ino = ino;
6296 pctx.dirent = dirent;
6297 fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
6298 if (!ctx->dirs_to_hash)
6299 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
6300 if (ctx->dirs_to_hash)
6301 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6302 dups_found++;
6303 } else
6304 dict_alloc_insert(&de_dict, dirent, dirent);
6305
6306 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
6307 &links);
6308 if (links > 1)
6309 ctx->fs_links_count++;
6310 ctx->fs_total_count++;
6311 next:
6312 prev = dirent;
6313 offset += dirent->rec_len;
6314 dot_state++;
6315 } while (offset < fs->blocksize);
6316#ifdef ENABLE_HTREE
6317 if (dx_db) {
6318 cd->pctx.dir = cd->pctx.ino;
6319 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
6320 (dx_db->type == DX_DIRBLOCK_NODE))
6321 parse_int_node(fs, db, cd, dx_dir, buf);
6322 }
6323#endif /* ENABLE_HTREE */
6324 if (offset != fs->blocksize) {
6325 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
6326 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
6327 dirent->rec_len = cd->pctx.num;
6328 dir_modified++;
6329 }
6330 }
6331 if (dir_modified) {
6332 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
6333 if (cd->pctx.errcode) {
6334 if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
6335 &cd->pctx))
6336 goto abort_free_dict;
6337 }
6338 ext2fs_mark_changed(fs);
6339 }
6340 dict_free_nodes(&de_dict);
6341 return 0;
6342abort_free_dict:
6343 dict_free_nodes(&de_dict);
6344 ctx->flags |= E2F_FLAG_ABORT;
6345 return DIRENT_ABORT;
6346}
6347
6348/*
6349 * This function is called to deallocate a block, and is an interator
6350 * functioned called by deallocate inode via ext2fs_iterate_block().
6351 */
6352static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
6353 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6354 blk_t ref_block FSCK_ATTR((unused)),
6355 int ref_offset FSCK_ATTR((unused)),
6356 void *priv_data)
6357{
6358 e2fsck_t ctx = (e2fsck_t) priv_data;
6359
6360 if (HOLE_BLKADDR(*block_nr))
6361 return 0;
6362 if ((*block_nr < fs->super->s_first_data_block) ||
6363 (*block_nr >= fs->super->s_blocks_count))
6364 return 0;
6365 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6366 ext2fs_block_alloc_stats(fs, *block_nr, -1);
6367 return 0;
6368}
6369
6370/*
6371 * This fuction deallocates an inode
6372 */
6373static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
6374{
6375 ext2_filsys fs = ctx->fs;
6376 struct ext2_inode inode;
6377 struct problem_context pctx;
6378 __u32 count;
6379
6380 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
6381 e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
6382 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00006383 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00006384 e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
6385 clear_problem_context(&pctx);
6386 pctx.ino = ino;
6387
6388 /*
6389 * Fix up the bitmaps...
6390 */
6391 e2fsck_read_bitmaps(ctx);
6392 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6393 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6394 if (ctx->inode_bad_map)
6395 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6396 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6397
6398 if (inode.i_file_acl &&
6399 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6400 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6401 block_buf, -1, &count);
6402 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6403 pctx.errcode = 0;
6404 count = 1;
6405 }
6406 if (pctx.errcode) {
6407 pctx.blk = inode.i_file_acl;
6408 fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
6409 ctx->flags |= E2F_FLAG_ABORT;
6410 return;
6411 }
6412 if (count == 0) {
6413 ext2fs_unmark_block_bitmap(ctx->block_found_map,
6414 inode.i_file_acl);
6415 ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
6416 }
6417 inode.i_file_acl = 0;
6418 }
6419
6420 if (!ext2fs_inode_has_valid_blocks(&inode))
6421 return;
6422
6423 if (LINUX_S_ISREG(inode.i_mode) &&
6424 (inode.i_size_high || inode.i_size & 0x80000000UL))
6425 ctx->large_files--;
6426
6427 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6428 deallocate_inode_block, ctx);
6429 if (pctx.errcode) {
6430 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
6431 ctx->flags |= E2F_FLAG_ABORT;
6432 return;
6433 }
6434}
6435
6436/*
6437 * This fuction clears the htree flag on an inode
6438 */
6439static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
6440{
6441 struct ext2_inode inode;
6442
6443 e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
6444 inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
6445 e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
6446 if (ctx->dirs_to_hash)
6447 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6448}
6449
6450
6451static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
6452 ext2_ino_t ino, char *buf)
6453{
6454 ext2_filsys fs = ctx->fs;
6455 struct ext2_inode inode;
6456 int inode_modified = 0;
6457 int not_fixed = 0;
6458 unsigned char *frag, *fsize;
6459 struct problem_context pctx;
6460 int problem = 0;
6461
6462 e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
6463
6464 clear_problem_context(&pctx);
6465 pctx.ino = ino;
6466 pctx.dir = dir;
6467 pctx.inode = &inode;
6468
6469 if (inode.i_file_acl &&
6470 !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
6471 fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
6472 inode.i_file_acl = 0;
6473#if BB_BIG_ENDIAN
6474 /*
6475 * This is a special kludge to deal with long symlinks
6476 * on big endian systems. i_blocks had already been
6477 * decremented earlier in pass 1, but since i_file_acl
6478 * hadn't yet been cleared, ext2fs_read_inode()
6479 * assumed that the file was short symlink and would
6480 * not have byte swapped i_block[0]. Hence, we have
6481 * to byte-swap it here.
6482 */
6483 if (LINUX_S_ISLNK(inode.i_mode) &&
6484 (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
6485 (inode.i_blocks == fs->blocksize >> 9))
6486 inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
6487#endif
6488 inode_modified++;
6489 } else
6490 not_fixed++;
6491
6492 if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
6493 !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
6494 !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
6495 !(LINUX_S_ISSOCK(inode.i_mode)))
6496 problem = PR_2_BAD_MODE;
6497 else if (LINUX_S_ISCHR(inode.i_mode)
6498 && !e2fsck_pass1_check_device_inode(fs, &inode))
6499 problem = PR_2_BAD_CHAR_DEV;
6500 else if (LINUX_S_ISBLK(inode.i_mode)
6501 && !e2fsck_pass1_check_device_inode(fs, &inode))
6502 problem = PR_2_BAD_BLOCK_DEV;
6503 else if (LINUX_S_ISFIFO(inode.i_mode)
6504 && !e2fsck_pass1_check_device_inode(fs, &inode))
6505 problem = PR_2_BAD_FIFO;
6506 else if (LINUX_S_ISSOCK(inode.i_mode)
6507 && !e2fsck_pass1_check_device_inode(fs, &inode))
6508 problem = PR_2_BAD_SOCKET;
6509 else if (LINUX_S_ISLNK(inode.i_mode)
6510 && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
6511 problem = PR_2_INVALID_SYMLINK;
6512 }
6513
6514 if (problem) {
6515 if (fix_problem(ctx, problem, &pctx)) {
6516 deallocate_inode(ctx, ino, 0);
6517 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6518 return 0;
6519 return 1;
6520 } else
6521 not_fixed++;
6522 problem = 0;
6523 }
6524
6525 if (inode.i_faddr) {
6526 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
6527 inode.i_faddr = 0;
6528 inode_modified++;
6529 } else
6530 not_fixed++;
6531 }
6532
6533 switch (fs->super->s_creator_os) {
6534 case EXT2_OS_LINUX:
6535 frag = &inode.osd2.linux2.l_i_frag;
6536 fsize = &inode.osd2.linux2.l_i_fsize;
6537 break;
6538 case EXT2_OS_HURD:
6539 frag = &inode.osd2.hurd2.h_i_frag;
6540 fsize = &inode.osd2.hurd2.h_i_fsize;
6541 break;
6542 case EXT2_OS_MASIX:
6543 frag = &inode.osd2.masix2.m_i_frag;
6544 fsize = &inode.osd2.masix2.m_i_fsize;
6545 break;
6546 default:
6547 frag = fsize = 0;
6548 }
6549 if (frag && *frag) {
6550 pctx.num = *frag;
6551 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
6552 *frag = 0;
6553 inode_modified++;
6554 } else
6555 not_fixed++;
6556 pctx.num = 0;
6557 }
6558 if (fsize && *fsize) {
6559 pctx.num = *fsize;
6560 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
6561 *fsize = 0;
6562 inode_modified++;
6563 } else
6564 not_fixed++;
6565 pctx.num = 0;
6566 }
6567
6568 if (inode.i_file_acl &&
6569 ((inode.i_file_acl < fs->super->s_first_data_block) ||
6570 (inode.i_file_acl >= fs->super->s_blocks_count))) {
6571 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
6572 inode.i_file_acl = 0;
6573 inode_modified++;
6574 } else
6575 not_fixed++;
6576 }
6577 if (inode.i_dir_acl &&
6578 LINUX_S_ISDIR(inode.i_mode)) {
6579 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
6580 inode.i_dir_acl = 0;
6581 inode_modified++;
6582 } else
6583 not_fixed++;
6584 }
6585
6586 if (inode_modified)
6587 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
6588 if (!not_fixed)
6589 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6590 return 0;
6591}
6592
6593
6594/*
6595 * allocate_dir_block --- this function allocates a new directory
6596 * block for a particular inode; this is done if a directory has
6597 * a "hole" in it, or if a directory has a illegal block number
6598 * that was zeroed out and now needs to be replaced.
6599 */
6600static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
6601 struct problem_context *pctx)
6602{
6603 ext2_filsys fs = ctx->fs;
6604 blk_t blk;
6605 char *block;
6606 struct ext2_inode inode;
6607
6608 if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
6609 return 1;
6610
6611 /*
6612 * Read the inode and block bitmaps in; we'll be messing with
6613 * them.
6614 */
6615 e2fsck_read_bitmaps(ctx);
6616
6617 /*
6618 * First, find a free block
6619 */
6620 pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6621 if (pctx->errcode) {
6622 pctx->str = "ext2fs_new_block";
6623 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6624 return 1;
6625 }
6626 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6627 ext2fs_mark_block_bitmap(fs->block_map, blk);
6628 ext2fs_mark_bb_dirty(fs);
6629
6630 /*
6631 * Now let's create the actual data block for the inode
6632 */
6633 if (db->blockcnt)
6634 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
6635 else
6636 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
6637 EXT2_ROOT_INO, &block);
6638
6639 if (pctx->errcode) {
6640 pctx->str = "ext2fs_new_dir_block";
6641 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6642 return 1;
6643 }
6644
6645 pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
6646 ext2fs_free_mem(&block);
6647 if (pctx->errcode) {
6648 pctx->str = "ext2fs_write_dir_block";
6649 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6650 return 1;
6651 }
6652
6653 /*
6654 * Update the inode block count
6655 */
6656 e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
6657 inode.i_blocks += fs->blocksize / 512;
6658 if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
6659 inode.i_size = (db->blockcnt+1) * fs->blocksize;
6660 e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
6661
6662 /*
6663 * Finally, update the block pointers for the inode
6664 */
6665 db->blk = blk;
6666 pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
6667 0, update_dir_block, db);
6668 if (pctx->errcode) {
6669 pctx->str = "ext2fs_block_iterate";
6670 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6671 return 1;
6672 }
6673
6674 return 0;
6675}
6676
6677/*
6678 * This is a helper function for allocate_dir_block().
6679 */
6680static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
6681 blk_t *block_nr,
6682 e2_blkcnt_t blockcnt,
6683 blk_t ref_block FSCK_ATTR((unused)),
6684 int ref_offset FSCK_ATTR((unused)),
6685 void *priv_data)
6686{
6687 struct ext2_db_entry *db;
6688
6689 db = (struct ext2_db_entry *) priv_data;
6690 if (db->blockcnt == (int) blockcnt) {
6691 *block_nr = db->blk;
6692 return BLOCK_CHANGED;
6693 }
6694 return 0;
6695}
6696
6697/*
6698 * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
6699 *
6700 * Pass #3 assures that all directories are connected to the
6701 * filesystem tree, using the following algorithm:
6702 *
6703 * First, the root directory is checked to make sure it exists; if
6704 * not, e2fsck will offer to create a new one. It is then marked as
6705 * "done".
6706 *
6707 * Then, pass3 interates over all directory inodes; for each directory
6708 * it attempts to trace up the filesystem tree, using dirinfo.parent
6709 * until it reaches a directory which has been marked "done". If it
6710 * cannot do so, then the directory must be disconnected, and e2fsck
6711 * will offer to reconnect it to /lost+found. While it is chasing
6712 * parent pointers up the filesystem tree, if pass3 sees a directory
6713 * twice, then it has detected a filesystem loop, and it will again
6714 * offer to reconnect the directory to /lost+found in to break the
6715 * filesystem loop.
6716 *
6717 * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
6718 * reconnect inodes to /lost+found; this subroutine is also used by
6719 * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which
6720 * is responsible for creating /lost+found if it does not exist.
6721 *
6722 * Pass 3 frees the following data structures:
6723 * - The dirinfo directory information cache.
6724 */
6725
6726static void check_root(e2fsck_t ctx);
6727static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6728 struct problem_context *pctx);
6729static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
6730
6731static ext2fs_inode_bitmap inode_loop_detect;
6732static ext2fs_inode_bitmap inode_done_map;
6733
6734static void e2fsck_pass3(e2fsck_t ctx)
6735{
6736 ext2_filsys fs = ctx->fs;
6737 int i;
6738 struct problem_context pctx;
6739 struct dir_info *dir;
6740 unsigned long maxdirs, count;
6741
6742 clear_problem_context(&pctx);
6743
6744 /* Pass 3 */
6745
6746 if (!(ctx->options & E2F_OPT_PREEN))
6747 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
6748
6749 /*
6750 * Allocate some bitmaps to do loop detection.
6751 */
6752 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
6753 &inode_done_map);
6754 if (pctx.errcode) {
6755 pctx.num = 2;
6756 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
6757 ctx->flags |= E2F_FLAG_ABORT;
6758 goto abort_exit;
6759 }
6760 check_root(ctx);
6761 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6762 goto abort_exit;
6763
6764 ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
6765
6766 maxdirs = e2fsck_get_num_dirinfo(ctx);
6767 count = 1;
6768
6769 if (ctx->progress)
6770 if ((ctx->progress)(ctx, 3, 0, maxdirs))
6771 goto abort_exit;
6772
6773 for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
6774 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6775 goto abort_exit;
6776 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
6777 goto abort_exit;
6778 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
6779 if (check_directory(ctx, dir, &pctx))
6780 goto abort_exit;
6781 }
6782
6783 /*
6784 * Force the creation of /lost+found if not present
6785 */
6786 if ((ctx->flags & E2F_OPT_READONLY) == 0)
6787 e2fsck_get_lost_and_found(ctx, 1);
6788
6789 /*
6790 * If there are any directories that need to be indexed or
6791 * optimized, do it here.
6792 */
6793 e2fsck_rehash_directories(ctx);
6794
6795abort_exit:
6796 e2fsck_free_dir_info(ctx);
6797 ext2fs_free_inode_bitmap(inode_loop_detect);
6798 inode_loop_detect = 0;
6799 ext2fs_free_inode_bitmap(inode_done_map);
6800 inode_done_map = 0;
6801}
6802
6803/*
6804 * This makes sure the root inode is present; if not, we ask if the
6805 * user wants us to create it. Not creating it is a fatal error.
6806 */
6807static void check_root(e2fsck_t ctx)
6808{
6809 ext2_filsys fs = ctx->fs;
6810 blk_t blk;
6811 struct ext2_inode inode;
6812 char * block;
6813 struct problem_context pctx;
6814
6815 clear_problem_context(&pctx);
6816
6817 if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
6818 /*
6819 * If the root inode is not a directory, die here. The
6820 * user must have answered 'no' in pass1 when we
6821 * offered to clear it.
6822 */
6823 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6824 EXT2_ROOT_INO))) {
6825 fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
6826 ctx->flags |= E2F_FLAG_ABORT;
6827 }
6828 return;
6829 }
6830
6831 if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
6832 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
6833 ctx->flags |= E2F_FLAG_ABORT;
6834 return;
6835 }
6836
6837 e2fsck_read_bitmaps(ctx);
6838
6839 /*
6840 * First, find a free block
6841 */
6842 pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6843 if (pctx.errcode) {
6844 pctx.str = "ext2fs_new_block";
6845 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6846 ctx->flags |= E2F_FLAG_ABORT;
6847 return;
6848 }
6849 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6850 ext2fs_mark_block_bitmap(fs->block_map, blk);
6851 ext2fs_mark_bb_dirty(fs);
6852
6853 /*
6854 * Now let's create the actual data block for the inode
6855 */
6856 pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
6857 &block);
6858 if (pctx.errcode) {
6859 pctx.str = "ext2fs_new_dir_block";
6860 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6861 ctx->flags |= E2F_FLAG_ABORT;
6862 return;
6863 }
6864
6865 pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
6866 if (pctx.errcode) {
6867 pctx.str = "ext2fs_write_dir_block";
6868 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6869 ctx->flags |= E2F_FLAG_ABORT;
6870 return;
6871 }
6872 ext2fs_free_mem(&block);
6873
6874 /*
6875 * Set up the inode structure
6876 */
6877 memset(&inode, 0, sizeof(inode));
6878 inode.i_mode = 040755;
6879 inode.i_size = fs->blocksize;
Denis Vlasenko04158e02009-02-02 10:48:06 +00006880 inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00006881 inode.i_links_count = 2;
6882 inode.i_blocks = fs->blocksize / 512;
6883 inode.i_block[0] = blk;
6884
6885 /*
6886 * Write out the inode.
6887 */
6888 pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
6889 if (pctx.errcode) {
6890 pctx.str = "ext2fs_write_inode";
6891 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6892 ctx->flags |= E2F_FLAG_ABORT;
6893 return;
6894 }
6895
6896 /*
6897 * Miscellaneous bookkeeping...
6898 */
6899 e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
6900 ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
6901 ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
6902
6903 ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
6904 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
6905 ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
6906 ext2fs_mark_ib_dirty(fs);
6907}
6908
6909/*
6910 * This subroutine is responsible for making sure that a particular
6911 * directory is connected to the root; if it isn't we trace it up as
6912 * far as we can go, and then offer to connect the resulting parent to
6913 * the lost+found. We have to do loop detection; if we ever discover
6914 * a loop, we treat that as a disconnected directory and offer to
6915 * reparent it to lost+found.
6916 *
6917 * However, loop detection is expensive, because for very large
6918 * filesystems, the inode_loop_detect bitmap is huge, and clearing it
6919 * is non-trivial. Loops in filesystems are also a rare error case,
6920 * and we shouldn't optimize for error cases. So we try two passes of
6921 * the algorithm. The first time, we ignore loop detection and merely
6922 * increment a counter; if the counter exceeds some extreme threshold,
6923 * then we try again with the loop detection bitmap enabled.
6924 */
6925static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6926 struct problem_context *pctx)
6927{
6928 ext2_filsys fs = ctx->fs;
6929 struct dir_info *p = dir;
6930 int loop_pass = 0, parent_count = 0;
6931
6932 if (!p)
6933 return 0;
6934
6935 while (1) {
6936 /*
6937 * Mark this inode as being "done"; by the time we
6938 * return from this function, the inode we either be
6939 * verified as being connected to the directory tree,
6940 * or we will have offered to reconnect this to
6941 * lost+found.
6942 *
6943 * If it was marked done already, then we've reached a
6944 * parent we've already checked.
6945 */
6946 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
6947 break;
6948
6949 /*
6950 * If this directory doesn't have a parent, or we've
6951 * seen the parent once already, then offer to
6952 * reparent it to lost+found
6953 */
6954 if (!p->parent ||
6955 (loop_pass &&
6956 (ext2fs_test_inode_bitmap(inode_loop_detect,
6957 p->parent)))) {
6958 pctx->ino = p->ino;
6959 if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
6960 if (e2fsck_reconnect_file(ctx, pctx->ino))
6961 ext2fs_unmark_valid(fs);
6962 else {
6963 p = e2fsck_get_dir_info(ctx, pctx->ino);
6964 p->parent = ctx->lost_and_found;
6965 fix_dotdot(ctx, p, ctx->lost_and_found);
6966 }
6967 }
6968 break;
6969 }
6970 p = e2fsck_get_dir_info(ctx, p->parent);
6971 if (!p) {
6972 fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
6973 return 0;
6974 }
6975 if (loop_pass) {
6976 ext2fs_mark_inode_bitmap(inode_loop_detect,
6977 p->ino);
6978 } else if (parent_count++ > 2048) {
6979 /*
6980 * If we've run into a path depth that's
6981 * greater than 2048, try again with the inode
6982 * loop bitmap turned on and start from the
6983 * top.
6984 */
6985 loop_pass = 1;
6986 if (inode_loop_detect)
6987 ext2fs_clear_inode_bitmap(inode_loop_detect);
6988 else {
6989 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
6990 if (pctx->errcode) {
6991 pctx->num = 1;
6992 fix_problem(ctx,
6993 PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
6994 ctx->flags |= E2F_FLAG_ABORT;
6995 return -1;
6996 }
6997 }
6998 p = dir;
6999 }
7000 }
7001
7002 /*
7003 * Make sure that .. and the parent directory are the same;
7004 * offer to fix it if not.
7005 */
7006 if (dir->parent != dir->dotdot) {
7007 pctx->ino = dir->ino;
7008 pctx->ino2 = dir->dotdot;
7009 pctx->dir = dir->parent;
7010 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
7011 fix_dotdot(ctx, dir, dir->parent);
7012 }
7013 return 0;
7014}
7015
7016/*
7017 * This routine gets the lost_and_found inode, making it a directory
7018 * if necessary
7019 */
7020ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
7021{
7022 ext2_filsys fs = ctx->fs;
7023 ext2_ino_t ino;
7024 blk_t blk;
7025 errcode_t retval;
7026 struct ext2_inode inode;
7027 char * block;
7028 static const char name[] = "lost+found";
7029 struct problem_context pctx;
7030 struct dir_info *dirinfo;
7031
7032 if (ctx->lost_and_found)
7033 return ctx->lost_and_found;
7034
7035 clear_problem_context(&pctx);
7036
7037 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
7038 sizeof(name)-1, 0, &ino);
7039 if (retval && !fix)
7040 return 0;
7041 if (!retval) {
7042 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
7043 ctx->lost_and_found = ino;
7044 return ino;
7045 }
7046
7047 /* Lost+found isn't a directory! */
7048 if (!fix)
7049 return 0;
7050 pctx.ino = ino;
7051 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
7052 return 0;
7053
7054 /* OK, unlink the old /lost+found file. */
7055 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
7056 if (pctx.errcode) {
7057 pctx.str = "ext2fs_unlink";
7058 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7059 return 0;
7060 }
7061 dirinfo = e2fsck_get_dir_info(ctx, ino);
7062 if (dirinfo)
7063 dirinfo->parent = 0;
7064 e2fsck_adjust_inode_count(ctx, ino, -1);
7065 } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
7066 pctx.errcode = retval;
7067 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
7068 }
7069 if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
7070 return 0;
7071
7072 /*
7073 * Read the inode and block bitmaps in; we'll be messing with
7074 * them.
7075 */
7076 e2fsck_read_bitmaps(ctx);
7077
7078 /*
7079 * First, find a free block
7080 */
7081 retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7082 if (retval) {
7083 pctx.errcode = retval;
7084 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
7085 return 0;
7086 }
7087 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7088 ext2fs_block_alloc_stats(fs, blk, +1);
7089
7090 /*
7091 * Next find a free inode.
7092 */
7093 retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
7094 ctx->inode_used_map, &ino);
7095 if (retval) {
7096 pctx.errcode = retval;
7097 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
7098 return 0;
7099 }
7100 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
7101 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
7102 ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
7103
7104 /*
7105 * Now let's create the actual data block for the inode
7106 */
7107 retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
7108 if (retval) {
7109 pctx.errcode = retval;
7110 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
7111 return 0;
7112 }
7113
7114 retval = ext2fs_write_dir_block(fs, blk, block);
7115 ext2fs_free_mem(&block);
7116 if (retval) {
7117 pctx.errcode = retval;
7118 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
7119 return 0;
7120 }
7121
7122 /*
7123 * Set up the inode structure
7124 */
7125 memset(&inode, 0, sizeof(inode));
7126 inode.i_mode = 040700;
7127 inode.i_size = fs->blocksize;
Denis Vlasenko04158e02009-02-02 10:48:06 +00007128 inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007129 inode.i_links_count = 2;
7130 inode.i_blocks = fs->blocksize / 512;
7131 inode.i_block[0] = blk;
7132
7133 /*
7134 * Next, write out the inode.
7135 */
7136 pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
7137 if (pctx.errcode) {
7138 pctx.str = "ext2fs_write_inode";
7139 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7140 return 0;
7141 }
7142 /*
7143 * Finally, create the directory link
7144 */
7145 pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
7146 if (pctx.errcode) {
7147 pctx.str = "ext2fs_link";
7148 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7149 return 0;
7150 }
7151
7152 /*
7153 * Miscellaneous bookkeeping that needs to be kept straight.
7154 */
7155 e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
7156 e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
7157 ext2fs_icount_store(ctx->inode_count, ino, 2);
7158 ext2fs_icount_store(ctx->inode_link_info, ino, 2);
7159 ctx->lost_and_found = ino;
7160 return ino;
7161}
7162
7163/*
7164 * This routine will connect a file to lost+found
7165 */
7166int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
7167{
7168 ext2_filsys fs = ctx->fs;
7169 errcode_t retval;
7170 char name[80];
7171 struct problem_context pctx;
7172 struct ext2_inode inode;
7173 int file_type = 0;
7174
7175 clear_problem_context(&pctx);
7176 pctx.ino = ino;
7177
7178 if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
7179 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
7180 ctx->bad_lost_and_found++;
7181 }
7182 if (ctx->bad_lost_and_found) {
7183 fix_problem(ctx, PR_3_NO_LPF, &pctx);
7184 return 1;
7185 }
7186
7187 sprintf(name, "#%u", ino);
7188 if (ext2fs_read_inode(fs, ino, &inode) == 0)
7189 file_type = ext2_file_type(inode.i_mode);
7190 retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
7191 if (retval == EXT2_ET_DIR_NO_SPACE) {
7192 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
7193 return 1;
7194 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
7195 1, 0);
7196 if (retval) {
7197 pctx.errcode = retval;
7198 fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
7199 return 1;
7200 }
7201 retval = ext2fs_link(fs, ctx->lost_and_found, name,
7202 ino, file_type);
7203 }
7204 if (retval) {
7205 pctx.errcode = retval;
7206 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
7207 return 1;
7208 }
7209 e2fsck_adjust_inode_count(ctx, ino, 1);
7210
7211 return 0;
7212}
7213
7214/*
7215 * Utility routine to adjust the inode counts on an inode.
7216 */
7217errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
7218{
7219 ext2_filsys fs = ctx->fs;
7220 errcode_t retval;
7221 struct ext2_inode inode;
7222
7223 if (!ino)
7224 return 0;
7225
7226 retval = ext2fs_read_inode(fs, ino, &inode);
7227 if (retval)
7228 return retval;
7229
7230 if (adj == 1) {
7231 ext2fs_icount_increment(ctx->inode_count, ino, 0);
7232 if (inode.i_links_count == (__u16) ~0)
7233 return 0;
7234 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
7235 inode.i_links_count++;
7236 } else if (adj == -1) {
7237 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
7238 if (inode.i_links_count == 0)
7239 return 0;
7240 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
7241 inode.i_links_count--;
7242 }
7243
7244 retval = ext2fs_write_inode(fs, ino, &inode);
7245 if (retval)
7246 return retval;
7247
7248 return 0;
7249}
7250
7251/*
7252 * Fix parent --- this routine fixes up the parent of a directory.
7253 */
7254struct fix_dotdot_struct {
7255 ext2_filsys fs;
7256 ext2_ino_t parent;
7257 int done;
7258 e2fsck_t ctx;
7259};
7260
7261static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
7262 int offset FSCK_ATTR((unused)),
7263 int blocksize FSCK_ATTR((unused)),
7264 char *buf FSCK_ATTR((unused)),
7265 void *priv_data)
7266{
7267 struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
7268 errcode_t retval;
7269 struct problem_context pctx;
7270
7271 if ((dirent->name_len & 0xFF) != 2)
7272 return 0;
7273 if (strncmp(dirent->name, "..", 2))
7274 return 0;
7275
7276 clear_problem_context(&pctx);
7277
7278 retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
7279 if (retval) {
7280 pctx.errcode = retval;
7281 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7282 }
7283 retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
7284 if (retval) {
7285 pctx.errcode = retval;
7286 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7287 }
7288 dirent->inode = fp->parent;
7289
7290 fp->done++;
7291 return DIRENT_ABORT | DIRENT_CHANGED;
7292}
7293
7294static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
7295{
7296 ext2_filsys fs = ctx->fs;
7297 errcode_t retval;
7298 struct fix_dotdot_struct fp;
7299 struct problem_context pctx;
7300
7301 fp.fs = fs;
7302 fp.parent = parent;
7303 fp.done = 0;
7304 fp.ctx = ctx;
7305
7306 retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
7307 0, fix_dotdot_proc, &fp);
7308 if (retval || !fp.done) {
7309 clear_problem_context(&pctx);
7310 pctx.ino = dir->ino;
7311 pctx.errcode = retval;
7312 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
7313 PR_3_FIX_PARENT_NOFIND, &pctx);
7314 ext2fs_unmark_valid(fs);
7315 }
7316 dir->dotdot = parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007317}
7318
7319/*
7320 * These routines are responsible for expanding a /lost+found if it is
7321 * too small.
7322 */
7323
7324struct expand_dir_struct {
7325 int num;
7326 int guaranteed_size;
7327 int newblocks;
7328 int last_block;
7329 errcode_t err;
7330 e2fsck_t ctx;
7331};
7332
7333static int expand_dir_proc(ext2_filsys fs,
7334 blk_t *blocknr,
7335 e2_blkcnt_t blockcnt,
7336 blk_t ref_block FSCK_ATTR((unused)),
7337 int ref_offset FSCK_ATTR((unused)),
7338 void *priv_data)
7339{
7340 struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
7341 blk_t new_blk;
7342 static blk_t last_blk = 0;
7343 char *block;
7344 errcode_t retval;
7345 e2fsck_t ctx;
7346
7347 ctx = es->ctx;
7348
7349 if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
7350 return BLOCK_ABORT;
7351
7352 if (blockcnt > 0)
7353 es->last_block = blockcnt;
7354 if (*blocknr) {
7355 last_blk = *blocknr;
7356 return 0;
7357 }
7358 retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
7359 &new_blk);
7360 if (retval) {
7361 es->err = retval;
7362 return BLOCK_ABORT;
7363 }
7364 if (blockcnt > 0) {
7365 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
7366 if (retval) {
7367 es->err = retval;
7368 return BLOCK_ABORT;
7369 }
7370 es->num--;
7371 retval = ext2fs_write_dir_block(fs, new_blk, block);
7372 } else {
7373 retval = ext2fs_get_mem(fs->blocksize, &block);
7374 if (retval) {
7375 es->err = retval;
7376 return BLOCK_ABORT;
7377 }
7378 memset(block, 0, fs->blocksize);
7379 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
7380 }
7381 if (retval) {
7382 es->err = retval;
7383 return BLOCK_ABORT;
7384 }
7385 ext2fs_free_mem(&block);
7386 *blocknr = new_blk;
7387 ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
7388 ext2fs_block_alloc_stats(fs, new_blk, +1);
7389 es->newblocks++;
7390
7391 if (es->num == 0)
7392 return (BLOCK_CHANGED | BLOCK_ABORT);
7393 else
7394 return BLOCK_CHANGED;
7395}
7396
7397errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
7398 int num, int guaranteed_size)
7399{
7400 ext2_filsys fs = ctx->fs;
7401 errcode_t retval;
7402 struct expand_dir_struct es;
7403 struct ext2_inode inode;
7404
7405 if (!(fs->flags & EXT2_FLAG_RW))
7406 return EXT2_ET_RO_FILSYS;
7407
7408 /*
7409 * Read the inode and block bitmaps in; we'll be messing with
7410 * them.
7411 */
7412 e2fsck_read_bitmaps(ctx);
7413
7414 retval = ext2fs_check_directory(fs, dir);
7415 if (retval)
7416 return retval;
7417
7418 es.num = num;
7419 es.guaranteed_size = guaranteed_size;
7420 es.last_block = 0;
7421 es.err = 0;
7422 es.newblocks = 0;
7423 es.ctx = ctx;
7424
7425 retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
7426 0, expand_dir_proc, &es);
7427
7428 if (es.err)
7429 return es.err;
7430
7431 /*
7432 * Update the size and block count fields in the inode.
7433 */
7434 retval = ext2fs_read_inode(fs, dir, &inode);
7435 if (retval)
7436 return retval;
7437
7438 inode.i_size = (es.last_block + 1) * fs->blocksize;
7439 inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
7440
7441 e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
7442
7443 return 0;
7444}
7445
7446/*
7447 * pass4.c -- pass #4 of e2fsck: Check reference counts
7448 *
7449 * Pass 4 frees the following data structures:
7450 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
7451 */
7452
7453/*
7454 * This routine is called when an inode is not connected to the
7455 * directory tree.
7456 *
7457 * This subroutine returns 1 then the caller shouldn't bother with the
7458 * rest of the pass 4 tests.
7459 */
7460static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
7461{
7462 ext2_filsys fs = ctx->fs;
7463 struct ext2_inode inode;
7464 struct problem_context pctx;
7465
7466 e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
7467 clear_problem_context(&pctx);
7468 pctx.ino = i;
7469 pctx.inode = &inode;
7470
7471 /*
7472 * Offer to delete any zero-length files that does not have
7473 * blocks. If there is an EA block, it might have useful
7474 * information, so we won't prompt to delete it, but let it be
7475 * reconnected to lost+found.
7476 */
7477 if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
7478 LINUX_S_ISDIR(inode.i_mode))) {
7479 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
7480 ext2fs_icount_store(ctx->inode_link_info, i, 0);
7481 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00007482 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007483 e2fsck_write_inode(ctx, i, &inode,
7484 "disconnect_inode");
7485 /*
7486 * Fix up the bitmaps...
7487 */
7488 e2fsck_read_bitmaps(ctx);
7489 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
7490 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
7491 ext2fs_inode_alloc_stats2(fs, i, -1,
7492 LINUX_S_ISDIR(inode.i_mode));
7493 return 0;
7494 }
7495 }
7496
7497 /*
7498 * Prompt to reconnect.
7499 */
7500 if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7501 if (e2fsck_reconnect_file(ctx, i))
7502 ext2fs_unmark_valid(fs);
7503 } else {
7504 /*
7505 * If we don't attach the inode, then skip the
7506 * i_links_test since there's no point in trying to
7507 * force i_links_count to zero.
7508 */
7509 ext2fs_unmark_valid(fs);
7510 return 1;
7511 }
7512 return 0;
7513}
7514
7515
7516static void e2fsck_pass4(e2fsck_t ctx)
7517{
7518 ext2_filsys fs = ctx->fs;
7519 ext2_ino_t i;
7520 struct ext2_inode inode;
7521 struct problem_context pctx;
7522 __u16 link_count, link_counted;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +01007523 char *buf = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007524 int group, maxgroup;
7525
7526 /* Pass 4 */
7527
7528 clear_problem_context(&pctx);
7529
7530 if (!(ctx->options & E2F_OPT_PREEN))
7531 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
7532
7533 group = 0;
7534 maxgroup = fs->group_desc_count;
7535 if (ctx->progress)
7536 if ((ctx->progress)(ctx, 4, 0, maxgroup))
7537 return;
7538
7539 for (i=1; i <= fs->super->s_inodes_count; i++) {
7540 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7541 return;
7542 if ((i % fs->super->s_inodes_per_group) == 0) {
7543 group++;
7544 if (ctx->progress)
7545 if ((ctx->progress)(ctx, 4, group, maxgroup))
7546 return;
7547 }
7548 if (i == EXT2_BAD_INO ||
7549 (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
7550 continue;
7551 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
7552 (ctx->inode_imagic_map &&
7553 ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
7554 continue;
7555 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
7556 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
7557 if (link_counted == 0) {
7558 if (!buf)
7559 buf = e2fsck_allocate_memory(ctx,
7560 fs->blocksize, "bad_inode buffer");
7561 if (e2fsck_process_bad_inode(ctx, 0, i, buf))
7562 continue;
7563 if (disconnect_inode(ctx, i))
7564 continue;
7565 ext2fs_icount_fetch(ctx->inode_link_info, i,
7566 &link_count);
7567 ext2fs_icount_fetch(ctx->inode_count, i,
7568 &link_counted);
7569 }
7570 if (link_counted != link_count) {
7571 e2fsck_read_inode(ctx, i, &inode, "pass4");
7572 pctx.ino = i;
7573 pctx.inode = &inode;
7574 if (link_count != inode.i_links_count) {
7575 pctx.num = link_count;
7576 fix_problem(ctx,
7577 PR_4_INCONSISTENT_COUNT, &pctx);
7578 }
7579 pctx.num = link_counted;
7580 if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
7581 inode.i_links_count = link_counted;
7582 e2fsck_write_inode(ctx, i, &inode, "pass4");
7583 }
7584 }
7585 }
7586 ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
7587 ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
7588 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
7589 ctx->inode_imagic_map = 0;
7590 ext2fs_free_mem(&buf);
7591}
7592
7593/*
7594 * pass5.c --- check block and inode bitmaps against on-disk bitmaps
7595 */
7596
7597#define NO_BLK ((blk_t) -1)
7598
7599static void print_bitmap_problem(e2fsck_t ctx, int problem,
7600 struct problem_context *pctx)
7601{
7602 switch (problem) {
7603 case PR_5_BLOCK_UNUSED:
7604 if (pctx->blk == pctx->blk2)
7605 pctx->blk2 = 0;
7606 else
7607 problem = PR_5_BLOCK_RANGE_UNUSED;
7608 break;
7609 case PR_5_BLOCK_USED:
7610 if (pctx->blk == pctx->blk2)
7611 pctx->blk2 = 0;
7612 else
7613 problem = PR_5_BLOCK_RANGE_USED;
7614 break;
7615 case PR_5_INODE_UNUSED:
7616 if (pctx->ino == pctx->ino2)
7617 pctx->ino2 = 0;
7618 else
7619 problem = PR_5_INODE_RANGE_UNUSED;
7620 break;
7621 case PR_5_INODE_USED:
7622 if (pctx->ino == pctx->ino2)
7623 pctx->ino2 = 0;
7624 else
7625 problem = PR_5_INODE_RANGE_USED;
7626 break;
7627 }
7628 fix_problem(ctx, problem, pctx);
7629 pctx->blk = pctx->blk2 = NO_BLK;
7630 pctx->ino = pctx->ino2 = 0;
7631}
7632
7633static void check_block_bitmaps(e2fsck_t ctx)
7634{
7635 ext2_filsys fs = ctx->fs;
7636 blk_t i;
7637 int *free_array;
7638 int group = 0;
7639 unsigned int blocks = 0;
7640 unsigned int free_blocks = 0;
7641 int group_free = 0;
7642 int actual, bitmap;
7643 struct problem_context pctx;
7644 int problem, save_problem, fixit, had_problem;
7645 errcode_t retval;
7646
7647 clear_problem_context(&pctx);
7648 free_array = (int *) e2fsck_allocate_memory(ctx,
7649 fs->group_desc_count * sizeof(int), "free block count array");
7650
7651 if ((fs->super->s_first_data_block <
7652 ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
7653 (fs->super->s_blocks_count-1 >
7654 ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
7655 pctx.num = 1;
7656 pctx.blk = fs->super->s_first_data_block;
7657 pctx.blk2 = fs->super->s_blocks_count -1;
7658 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
7659 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
7660 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7661
7662 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7663 return;
7664 }
7665
7666 if ((fs->super->s_first_data_block <
7667 ext2fs_get_block_bitmap_start(fs->block_map)) ||
7668 (fs->super->s_blocks_count-1 >
7669 ext2fs_get_block_bitmap_end(fs->block_map))) {
7670 pctx.num = 2;
7671 pctx.blk = fs->super->s_first_data_block;
7672 pctx.blk2 = fs->super->s_blocks_count -1;
7673 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
7674 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
7675 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7676
7677 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7678 return;
7679 }
7680
7681redo_counts:
7682 had_problem = 0;
7683 save_problem = 0;
7684 pctx.blk = pctx.blk2 = NO_BLK;
7685 for (i = fs->super->s_first_data_block;
7686 i < fs->super->s_blocks_count;
7687 i++) {
7688 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
7689 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
7690
7691 if (actual == bitmap)
7692 goto do_counts;
7693
7694 if (!actual && bitmap) {
7695 /*
7696 * Block not used, but marked in use in the bitmap.
7697 */
7698 problem = PR_5_BLOCK_UNUSED;
7699 } else {
7700 /*
7701 * Block used, but not marked in use in the bitmap.
7702 */
7703 problem = PR_5_BLOCK_USED;
7704 }
7705 if (pctx.blk == NO_BLK) {
7706 pctx.blk = pctx.blk2 = i;
7707 save_problem = problem;
7708 } else {
7709 if ((problem == save_problem) &&
7710 (pctx.blk2 == i-1))
7711 pctx.blk2++;
7712 else {
7713 print_bitmap_problem(ctx, save_problem, &pctx);
7714 pctx.blk = pctx.blk2 = i;
7715 save_problem = problem;
7716 }
7717 }
7718 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7719 had_problem++;
7720
7721 do_counts:
7722 if (!bitmap) {
7723 group_free++;
7724 free_blocks++;
7725 }
7726 blocks ++;
7727 if ((blocks == fs->super->s_blocks_per_group) ||
7728 (i == fs->super->s_blocks_count-1)) {
7729 free_array[group] = group_free;
7730 group ++;
7731 blocks = 0;
7732 group_free = 0;
7733 if (ctx->progress)
7734 if ((ctx->progress)(ctx, 5, group,
7735 fs->group_desc_count*2))
7736 return;
7737 }
7738 }
7739 if (pctx.blk != NO_BLK)
7740 print_bitmap_problem(ctx, save_problem, &pctx);
7741 if (had_problem)
7742 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
7743 else
7744 fixit = -1;
7745 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7746
7747 if (fixit == 1) {
7748 ext2fs_free_block_bitmap(fs->block_map);
7749 retval = ext2fs_copy_bitmap(ctx->block_found_map,
7750 &fs->block_map);
7751 if (retval) {
7752 clear_problem_context(&pctx);
7753 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
7754 ctx->flags |= E2F_FLAG_ABORT;
7755 return;
7756 }
7757 ext2fs_set_bitmap_padding(fs->block_map);
7758 ext2fs_mark_bb_dirty(fs);
7759
7760 /* Redo the counts */
7761 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
7762 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7763 goto redo_counts;
7764 } else if (fixit == 0)
7765 ext2fs_unmark_valid(fs);
7766
7767 for (i = 0; i < fs->group_desc_count; i++) {
7768 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
7769 pctx.group = i;
7770 pctx.blk = fs->group_desc[i].bg_free_blocks_count;
7771 pctx.blk2 = free_array[i];
7772
7773 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
7774 &pctx)) {
7775 fs->group_desc[i].bg_free_blocks_count =
7776 free_array[i];
7777 ext2fs_mark_super_dirty(fs);
7778 } else
7779 ext2fs_unmark_valid(fs);
7780 }
7781 }
7782 if (free_blocks != fs->super->s_free_blocks_count) {
7783 pctx.group = 0;
7784 pctx.blk = fs->super->s_free_blocks_count;
7785 pctx.blk2 = free_blocks;
7786
7787 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
7788 fs->super->s_free_blocks_count = free_blocks;
7789 ext2fs_mark_super_dirty(fs);
7790 } else
7791 ext2fs_unmark_valid(fs);
7792 }
7793 ext2fs_free_mem(&free_array);
7794}
7795
7796static void check_inode_bitmaps(e2fsck_t ctx)
7797{
7798 ext2_filsys fs = ctx->fs;
7799 ext2_ino_t i;
7800 unsigned int free_inodes = 0;
7801 int group_free = 0;
7802 int dirs_count = 0;
7803 int group = 0;
7804 unsigned int inodes = 0;
7805 int *free_array;
7806 int *dir_array;
7807 int actual, bitmap;
7808 errcode_t retval;
7809 struct problem_context pctx;
7810 int problem, save_problem, fixit, had_problem;
7811
7812 clear_problem_context(&pctx);
7813 free_array = (int *) e2fsck_allocate_memory(ctx,
7814 fs->group_desc_count * sizeof(int), "free inode count array");
7815
7816 dir_array = (int *) e2fsck_allocate_memory(ctx,
7817 fs->group_desc_count * sizeof(int), "directory count array");
7818
7819 if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
7820 (fs->super->s_inodes_count >
7821 ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
7822 pctx.num = 3;
7823 pctx.blk = 1;
7824 pctx.blk2 = fs->super->s_inodes_count;
7825 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
7826 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
7827 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7828
7829 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7830 return;
7831 }
7832 if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
7833 (fs->super->s_inodes_count >
7834 ext2fs_get_inode_bitmap_end(fs->inode_map))) {
7835 pctx.num = 4;
7836 pctx.blk = 1;
7837 pctx.blk2 = fs->super->s_inodes_count;
7838 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
7839 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
7840 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7841
7842 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7843 return;
7844 }
7845
7846redo_counts:
7847 had_problem = 0;
7848 save_problem = 0;
7849 pctx.ino = pctx.ino2 = 0;
7850 for (i = 1; i <= fs->super->s_inodes_count; i++) {
7851 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
7852 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
7853
7854 if (actual == bitmap)
7855 goto do_counts;
7856
7857 if (!actual && bitmap) {
7858 /*
7859 * Inode wasn't used, but marked in bitmap
7860 */
7861 problem = PR_5_INODE_UNUSED;
7862 } else /* if (actual && !bitmap) */ {
7863 /*
7864 * Inode used, but not in bitmap
7865 */
7866 problem = PR_5_INODE_USED;
7867 }
7868 if (pctx.ino == 0) {
7869 pctx.ino = pctx.ino2 = i;
7870 save_problem = problem;
7871 } else {
7872 if ((problem == save_problem) &&
7873 (pctx.ino2 == i-1))
7874 pctx.ino2++;
7875 else {
7876 print_bitmap_problem(ctx, save_problem, &pctx);
7877 pctx.ino = pctx.ino2 = i;
7878 save_problem = problem;
7879 }
7880 }
7881 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7882 had_problem++;
7883
7884do_counts:
7885 if (!bitmap) {
7886 group_free++;
7887 free_inodes++;
7888 } else {
7889 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
7890 dirs_count++;
7891 }
7892 inodes++;
7893 if ((inodes == fs->super->s_inodes_per_group) ||
7894 (i == fs->super->s_inodes_count)) {
7895 free_array[group] = group_free;
7896 dir_array[group] = dirs_count;
7897 group ++;
7898 inodes = 0;
7899 group_free = 0;
7900 dirs_count = 0;
7901 if (ctx->progress)
7902 if ((ctx->progress)(ctx, 5,
7903 group + fs->group_desc_count,
7904 fs->group_desc_count*2))
7905 return;
7906 }
7907 }
7908 if (pctx.ino)
7909 print_bitmap_problem(ctx, save_problem, &pctx);
7910
7911 if (had_problem)
7912 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
7913 else
7914 fixit = -1;
7915 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7916
7917 if (fixit == 1) {
7918 ext2fs_free_inode_bitmap(fs->inode_map);
7919 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
7920 &fs->inode_map);
7921 if (retval) {
7922 clear_problem_context(&pctx);
7923 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
7924 ctx->flags |= E2F_FLAG_ABORT;
7925 return;
7926 }
7927 ext2fs_set_bitmap_padding(fs->inode_map);
7928 ext2fs_mark_ib_dirty(fs);
7929
7930 /* redo counts */
7931 inodes = 0; free_inodes = 0; group_free = 0;
7932 dirs_count = 0; group = 0;
7933 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7934 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
7935 goto redo_counts;
7936 } else if (fixit == 0)
7937 ext2fs_unmark_valid(fs);
7938
7939 for (i = 0; i < fs->group_desc_count; i++) {
7940 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
7941 pctx.group = i;
7942 pctx.ino = fs->group_desc[i].bg_free_inodes_count;
7943 pctx.ino2 = free_array[i];
7944 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
7945 &pctx)) {
7946 fs->group_desc[i].bg_free_inodes_count =
7947 free_array[i];
7948 ext2fs_mark_super_dirty(fs);
7949 } else
7950 ext2fs_unmark_valid(fs);
7951 }
7952 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
7953 pctx.group = i;
7954 pctx.ino = fs->group_desc[i].bg_used_dirs_count;
7955 pctx.ino2 = dir_array[i];
7956
7957 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
7958 &pctx)) {
7959 fs->group_desc[i].bg_used_dirs_count =
7960 dir_array[i];
7961 ext2fs_mark_super_dirty(fs);
7962 } else
7963 ext2fs_unmark_valid(fs);
7964 }
7965 }
7966 if (free_inodes != fs->super->s_free_inodes_count) {
7967 pctx.group = -1;
7968 pctx.ino = fs->super->s_free_inodes_count;
7969 pctx.ino2 = free_inodes;
7970
7971 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
7972 fs->super->s_free_inodes_count = free_inodes;
7973 ext2fs_mark_super_dirty(fs);
7974 } else
7975 ext2fs_unmark_valid(fs);
7976 }
7977 ext2fs_free_mem(&free_array);
7978 ext2fs_free_mem(&dir_array);
7979}
7980
7981static void check_inode_end(e2fsck_t ctx)
7982{
7983 ext2_filsys fs = ctx->fs;
7984 ext2_ino_t end, save_inodes_count, i;
7985 struct problem_context pctx;
7986
7987 clear_problem_context(&pctx);
7988
7989 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
7990 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
7991 &save_inodes_count);
7992 if (pctx.errcode) {
7993 pctx.num = 1;
7994 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
7995 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7996 return;
7997 }
7998 if (save_inodes_count == end)
7999 return;
8000
8001 for (i = save_inodes_count + 1; i <= end; i++) {
8002 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
8003 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
8004 for (i = save_inodes_count + 1; i <= end; i++)
8005 ext2fs_mark_inode_bitmap(fs->inode_map,
8006 i);
8007 ext2fs_mark_ib_dirty(fs);
8008 } else
8009 ext2fs_unmark_valid(fs);
8010 break;
8011 }
8012 }
8013
8014 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
8015 save_inodes_count, 0);
8016 if (pctx.errcode) {
8017 pctx.num = 2;
8018 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8019 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8020 return;
8021 }
8022}
8023
8024static void check_block_end(e2fsck_t ctx)
8025{
8026 ext2_filsys fs = ctx->fs;
8027 blk_t end, save_blocks_count, i;
8028 struct problem_context pctx;
8029
8030 clear_problem_context(&pctx);
8031
8032 end = fs->block_map->start +
8033 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
8034 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
8035 &save_blocks_count);
8036 if (pctx.errcode) {
8037 pctx.num = 3;
8038 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8039 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8040 return;
8041 }
8042 if (save_blocks_count == end)
8043 return;
8044
8045 for (i = save_blocks_count + 1; i <= end; i++) {
8046 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
8047 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
8048 for (i = save_blocks_count + 1; i <= end; i++)
8049 ext2fs_mark_block_bitmap(fs->block_map,
8050 i);
8051 ext2fs_mark_bb_dirty(fs);
8052 } else
8053 ext2fs_unmark_valid(fs);
8054 break;
8055 }
8056 }
8057
8058 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
8059 save_blocks_count, 0);
8060 if (pctx.errcode) {
8061 pctx.num = 4;
8062 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8063 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8064 return;
8065 }
8066}
8067
8068static void e2fsck_pass5(e2fsck_t ctx)
8069{
8070 struct problem_context pctx;
8071
8072 /* Pass 5 */
8073
8074 clear_problem_context(&pctx);
8075
8076 if (!(ctx->options & E2F_OPT_PREEN))
8077 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
8078
8079 if (ctx->progress)
8080 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
8081 return;
8082
8083 e2fsck_read_bitmaps(ctx);
8084
8085 check_block_bitmaps(ctx);
8086 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8087 return;
8088 check_inode_bitmaps(ctx);
8089 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8090 return;
8091 check_inode_end(ctx);
8092 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8093 return;
8094 check_block_end(ctx);
8095 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8096 return;
8097
8098 ext2fs_free_inode_bitmap(ctx->inode_used_map);
8099 ctx->inode_used_map = 0;
8100 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
8101 ctx->inode_dir_map = 0;
8102 ext2fs_free_block_bitmap(ctx->block_found_map);
8103 ctx->block_found_map = 0;
8104}
8105
8106/*
8107 * problem.c --- report filesystem problems to the user
8108 */
8109
8110#define PR_PREEN_OK 0x000001 /* Don't need to do preenhalt */
8111#define PR_NO_OK 0x000002 /* If user answers no, don't make fs invalid */
8112#define PR_NO_DEFAULT 0x000004 /* Default to no */
8113#define PR_MSG_ONLY 0x000008 /* Print message only */
8114
8115/* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
8116
8117#define PR_FATAL 0x001000 /* Fatal error */
8118#define PR_AFTER_CODE 0x002000 /* After asking the first question, */
8119 /* ask another */
8120#define PR_PREEN_NOMSG 0x004000 /* Don't print a message if we're preening */
8121#define PR_NOCOLLATE 0x008000 /* Don't collate answers for this latch */
8122#define PR_NO_NOMSG 0x010000 /* Don't print a message if e2fsck -n */
8123#define PR_PREEN_NO 0x020000 /* Use No as an answer if preening */
8124#define PR_PREEN_NOHDR 0x040000 /* Don't print the preen header */
8125
8126
8127#define PROMPT_NONE 0
8128#define PROMPT_FIX 1
8129#define PROMPT_CLEAR 2
8130#define PROMPT_RELOCATE 3
8131#define PROMPT_ALLOCATE 4
8132#define PROMPT_EXPAND 5
8133#define PROMPT_CONNECT 6
8134#define PROMPT_CREATE 7
8135#define PROMPT_SALVAGE 8
8136#define PROMPT_TRUNCATE 9
8137#define PROMPT_CLEAR_INODE 10
8138#define PROMPT_ABORT 11
8139#define PROMPT_SPLIT 12
8140#define PROMPT_CONTINUE 13
8141#define PROMPT_CLONE 14
8142#define PROMPT_DELETE 15
8143#define PROMPT_SUPPRESS 16
8144#define PROMPT_UNLINK 17
8145#define PROMPT_CLEAR_HTREE 18
8146#define PROMPT_RECREATE 19
8147#define PROMPT_NULL 20
8148
8149struct e2fsck_problem {
8150 problem_t e2p_code;
8151 const char * e2p_description;
8152 char prompt;
8153 int flags;
8154 problem_t second_code;
8155};
8156
8157struct latch_descr {
8158 int latch_code;
8159 problem_t question;
8160 problem_t end_message;
8161 int flags;
8162};
8163
8164/*
8165 * These are the prompts which are used to ask the user if they want
8166 * to fix a problem.
8167 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00008168static const char *const prompt[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00008169 N_("(no prompt)"), /* 0 */
8170 N_("Fix"), /* 1 */
8171 N_("Clear"), /* 2 */
8172 N_("Relocate"), /* 3 */
8173 N_("Allocate"), /* 4 */
8174 N_("Expand"), /* 5 */
8175 N_("Connect to /lost+found"), /* 6 */
8176 N_("Create"), /* 7 */
8177 N_("Salvage"), /* 8 */
8178 N_("Truncate"), /* 9 */
8179 N_("Clear inode"), /* 10 */
8180 N_("Abort"), /* 11 */
8181 N_("Split"), /* 12 */
8182 N_("Continue"), /* 13 */
8183 N_("Clone multiply-claimed blocks"), /* 14 */
8184 N_("Delete file"), /* 15 */
8185 N_("Suppress messages"),/* 16 */
8186 N_("Unlink"), /* 17 */
8187 N_("Clear HTree index"),/* 18 */
8188 N_("Recreate"), /* 19 */
8189 "", /* 20 */
8190};
8191
8192/*
8193 * These messages are printed when we are preen mode and we will be
8194 * automatically fixing the problem.
8195 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00008196static const char *const preen_msg[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00008197 N_("(NONE)"), /* 0 */
8198 N_("FIXED"), /* 1 */
8199 N_("CLEARED"), /* 2 */
8200 N_("RELOCATED"), /* 3 */
8201 N_("ALLOCATED"), /* 4 */
8202 N_("EXPANDED"), /* 5 */
8203 N_("RECONNECTED"), /* 6 */
8204 N_("CREATED"), /* 7 */
8205 N_("SALVAGED"), /* 8 */
8206 N_("TRUNCATED"), /* 9 */
8207 N_("INODE CLEARED"), /* 10 */
8208 N_("ABORTED"), /* 11 */
8209 N_("SPLIT"), /* 12 */
8210 N_("CONTINUING"), /* 13 */
8211 N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
8212 N_("FILE DELETED"), /* 15 */
8213 N_("SUPPRESSED"), /* 16 */
8214 N_("UNLINKED"), /* 17 */
8215 N_("HTREE INDEX CLEARED"),/* 18 */
8216 N_("WILL RECREATE"), /* 19 */
8217 "", /* 20 */
8218};
8219
8220static const struct e2fsck_problem problem_table[] = {
8221
8222 /* Pre-Pass 1 errors */
8223
8224 /* Block bitmap not in group */
8225 { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g. (@b %b)\n"),
8226 PROMPT_RELOCATE, PR_LATCH_RELOC },
8227
8228 /* Inode bitmap not in group */
8229 { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g. (@b %b)\n"),
8230 PROMPT_RELOCATE, PR_LATCH_RELOC },
8231
8232 /* Inode table not in group */
8233 { PR_0_ITABLE_NOT_GROUP,
8234 N_("@i table for @g %g is not in @g. (@b %b)\n"
8235 "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
8236 PROMPT_RELOCATE, PR_LATCH_RELOC },
8237
8238 /* Superblock corrupt */
8239 { PR_0_SB_CORRUPT,
8240 N_("\nThe @S could not be read or does not describe a correct ext2\n"
8241 "@f. If the @v is valid and it really contains an ext2\n"
8242 "@f (and not swap or ufs or something else), then the @S\n"
8243 "is corrupt, and you might try running e2fsck with an alternate @S:\n"
8244 " e2fsck -b %S <@v>\n\n"),
8245 PROMPT_NONE, PR_FATAL },
8246
8247 /* Filesystem size is wrong */
8248 { PR_0_FS_SIZE_WRONG,
8249 N_("The @f size (according to the @S) is %b @bs\n"
8250 "The physical size of the @v is %c @bs\n"
8251 "Either the @S or the partition table is likely to be corrupt!\n"),
8252 PROMPT_ABORT, 0 },
8253
8254 /* Fragments not supported */
8255 { PR_0_NO_FRAGMENTS,
8256 N_("@S @b_size = %b, fragsize = %c.\n"
8257 "This version of e2fsck does not support fragment sizes different\n"
8258 "from the @b size.\n"),
8259 PROMPT_NONE, PR_FATAL },
8260
8261 /* Bad blocks_per_group */
8262 { PR_0_BLOCKS_PER_GROUP,
8263 N_("@S @bs_per_group = %b, should have been %c\n"),
8264 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8265
8266 /* Bad first_data_block */
8267 { PR_0_FIRST_DATA_BLOCK,
8268 N_("@S first_data_@b = %b, should have been %c\n"),
8269 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8270
8271 /* Adding UUID to filesystem */
8272 { PR_0_ADD_UUID,
8273 N_("@f did not have a UUID; generating one.\n\n"),
8274 PROMPT_NONE, 0 },
8275
8276 /* Relocate hint */
8277 { PR_0_RELOCATE_HINT,
8278 N_("Note: if several inode or block bitmap blocks or part\n"
8279 "of the inode table require relocation, you may wish to try\n"
8280 "running e2fsck with the '-b %S' option first. The problem\n"
8281 "may lie only with the primary block group descriptors, and\n"
8282 "the backup block group descriptors may be OK.\n\n"),
8283 PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
8284
8285 /* Miscellaneous superblock corruption */
8286 { PR_0_MISC_CORRUPT_SUPER,
8287 N_("Corruption found in @S. (%s = %N).\n"),
8288 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8289
8290 /* Error determing physical device size of filesystem */
8291 { PR_0_GETSIZE_ERROR,
8292 N_("Error determining size of the physical @v: %m\n"),
8293 PROMPT_NONE, PR_FATAL },
8294
8295 /* Inode count in superblock is incorrect */
8296 { PR_0_INODE_COUNT_WRONG,
8297 N_("@i count in @S is %i, @s %j.\n"),
8298 PROMPT_FIX, 0 },
8299
8300 { PR_0_HURD_CLEAR_FILETYPE,
8301 N_("The Hurd does not support the filetype feature.\n"),
8302 PROMPT_CLEAR, 0 },
8303
8304 /* Journal inode is invalid */
8305 { PR_0_JOURNAL_BAD_INODE,
8306 N_("@S has an @n ext3 @j (@i %i).\n"),
8307 PROMPT_CLEAR, PR_PREEN_OK },
8308
8309 /* The external journal has (unsupported) multiple filesystems */
8310 { PR_0_JOURNAL_UNSUPP_MULTIFS,
8311 N_("External @j has multiple @f users (unsupported).\n"),
8312 PROMPT_NONE, PR_FATAL },
8313
8314 /* Can't find external journal */
8315 { PR_0_CANT_FIND_JOURNAL,
8316 N_("Can't find external @j\n"),
8317 PROMPT_NONE, PR_FATAL },
8318
8319 /* External journal has bad superblock */
8320 { PR_0_EXT_JOURNAL_BAD_SUPER,
8321 N_("External @j has bad @S\n"),
8322 PROMPT_NONE, PR_FATAL },
8323
8324 /* Superblock has a bad journal UUID */
8325 { PR_0_JOURNAL_BAD_UUID,
8326 N_("External @j does not support this @f\n"),
8327 PROMPT_NONE, PR_FATAL },
8328
8329 /* Journal has an unknown superblock type */
8330 { PR_0_JOURNAL_UNSUPP_SUPER,
8331 N_("Ext3 @j @S is unknown type %N (unsupported).\n"
8332 "It is likely that your copy of e2fsck is old and/or doesn't "
8333 "support this @j format.\n"
8334 "It is also possible the @j @S is corrupt.\n"),
8335 PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
8336
8337 /* Journal superblock is corrupt */
8338 { PR_0_JOURNAL_BAD_SUPER,
8339 N_("Ext3 @j @S is corrupt.\n"),
8340 PROMPT_FIX, PR_PREEN_OK },
8341
8342 /* Superblock flag should be cleared */
8343 { PR_0_JOURNAL_HAS_JOURNAL,
8344 N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
8345 PROMPT_CLEAR, PR_PREEN_OK },
8346
8347 /* Superblock flag is incorrect */
8348 { PR_0_JOURNAL_RECOVER_SET,
8349 N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
8350 PROMPT_CLEAR, PR_PREEN_OK },
8351
8352 /* Journal has data, but recovery flag is clear */
8353 { PR_0_JOURNAL_RECOVERY_CLEAR,
8354 N_("ext3 recovery flag is clear, but @j has data.\n"),
8355 PROMPT_NONE, 0 },
8356
8357 /* Ask if we should clear the journal */
8358 { PR_0_JOURNAL_RESET_JOURNAL,
8359 N_("Clear @j"),
8360 PROMPT_NULL, PR_PREEN_NOMSG },
8361
8362 /* Ask if we should run the journal anyway */
8363 { PR_0_JOURNAL_RUN,
8364 N_("Run @j anyway"),
8365 PROMPT_NULL, 0 },
8366
8367 /* Run the journal by default */
8368 { PR_0_JOURNAL_RUN_DEFAULT,
8369 N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
8370 PROMPT_NONE, 0 },
8371
8372 /* Clearing orphan inode */
8373 { PR_0_ORPHAN_CLEAR_INODE,
8374 N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
8375 PROMPT_NONE, 0 },
8376
8377 /* Illegal block found in orphaned inode */
8378 { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
8379 N_("@I @b #%B (%b) found in @o @i %i.\n"),
8380 PROMPT_NONE, 0 },
8381
8382 /* Already cleared block found in orphaned inode */
8383 { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
8384 N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
8385 PROMPT_NONE, 0 },
8386
8387 /* Illegal orphan inode in superblock */
8388 { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
8389 N_("@I @o @i %i in @S.\n"),
8390 PROMPT_NONE, 0 },
8391
8392 /* Illegal inode in orphaned inode list */
8393 { PR_0_ORPHAN_ILLEGAL_INODE,
8394 N_("@I @i %i in @o @i list.\n"),
8395 PROMPT_NONE, 0 },
8396
8397 /* Filesystem revision is 0, but feature flags are set */
8398 { PR_0_FS_REV_LEVEL,
8399 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8400 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8401
8402 /* Journal superblock has an unknown read-only feature flag set */
8403 { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
8404 N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
8405 PROMPT_ABORT, 0 },
8406
8407 /* Journal superblock has an unknown incompatible feature flag set */
8408 { PR_0_JOURNAL_UNSUPP_INCOMPAT,
8409 N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
8410 PROMPT_ABORT, 0 },
8411
8412 /* Journal has unsupported version number */
8413 { PR_0_JOURNAL_UNSUPP_VERSION,
8414 N_("@j version not supported by this e2fsck.\n"),
8415 PROMPT_ABORT, 0 },
8416
8417 /* Moving journal to hidden file */
8418 { PR_0_MOVE_JOURNAL,
8419 N_("Moving @j from /%s to hidden @i.\n\n"),
8420 PROMPT_NONE, 0 },
8421
8422 /* Error moving journal to hidden file */
8423 { PR_0_ERR_MOVE_JOURNAL,
8424 N_("Error moving @j: %m\n\n"),
8425 PROMPT_NONE, 0 },
8426
8427 /* Clearing V2 journal superblock */
8428 { PR_0_CLEAR_V2_JOURNAL,
8429 N_("Found @n V2 @j @S fields (from V1 @j).\n"
8430 "Clearing fields beyond the V1 @j @S...\n\n"),
8431 PROMPT_NONE, 0 },
8432
8433 /* Backup journal inode blocks */
8434 { PR_0_BACKUP_JNL,
8435 N_("Backing up @j @i @b information.\n\n"),
8436 PROMPT_NONE, 0 },
8437
8438 /* Reserved blocks w/o resize_inode */
8439 { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
8440 N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
8441 "is %N; @s zero. "),
8442 PROMPT_FIX, 0 },
8443
8444 /* Resize_inode not enabled, but resize inode is non-zero */
8445 { PR_0_CLEAR_RESIZE_INODE,
8446 N_("Resize_@i not enabled, but the resize @i is non-zero. "),
8447 PROMPT_CLEAR, 0 },
8448
8449 /* Resize inode invalid */
8450 { PR_0_RESIZE_INODE_INVALID,
8451 N_("Resize @i not valid. "),
8452 PROMPT_RECREATE, 0 },
8453
8454 /* Pass 1 errors */
8455
8456 /* Pass 1: Checking inodes, blocks, and sizes */
8457 { PR_1_PASS_HEADER,
8458 N_("Pass 1: Checking @is, @bs, and sizes\n"),
8459 PROMPT_NONE, 0 },
8460
8461 /* Root directory is not an inode */
8462 { PR_1_ROOT_NO_DIR, N_("@r is not a @d. "),
8463 PROMPT_CLEAR, 0 },
8464
8465 /* Root directory has dtime set */
8466 { PR_1_ROOT_DTIME,
8467 N_("@r has dtime set (probably due to old mke2fs). "),
8468 PROMPT_FIX, PR_PREEN_OK },
8469
8470 /* Reserved inode has bad mode */
8471 { PR_1_RESERVED_BAD_MODE,
8472 N_("Reserved @i %i (%Q) has @n mode. "),
8473 PROMPT_CLEAR, PR_PREEN_OK },
8474
8475 /* Deleted inode has zero dtime */
8476 { PR_1_ZERO_DTIME,
8477 N_("@D @i %i has zero dtime. "),
8478 PROMPT_FIX, PR_PREEN_OK },
8479
8480 /* Inode in use, but dtime set */
8481 { PR_1_SET_DTIME,
8482 N_("@i %i is in use, but has dtime set. "),
8483 PROMPT_FIX, PR_PREEN_OK },
8484
8485 /* Zero-length directory */
8486 { PR_1_ZERO_LENGTH_DIR,
8487 N_("@i %i is a @z @d. "),
8488 PROMPT_CLEAR, PR_PREEN_OK },
8489
8490 /* Block bitmap conflicts with some other fs block */
8491 { PR_1_BB_CONFLICT,
8492 N_("@g %g's @b @B at %b @C.\n"),
8493 PROMPT_RELOCATE, 0 },
8494
8495 /* Inode bitmap conflicts with some other fs block */
8496 { PR_1_IB_CONFLICT,
8497 N_("@g %g's @i @B at %b @C.\n"),
8498 PROMPT_RELOCATE, 0 },
8499
8500 /* Inode table conflicts with some other fs block */
8501 { PR_1_ITABLE_CONFLICT,
8502 N_("@g %g's @i table at %b @C.\n"),
8503 PROMPT_RELOCATE, 0 },
8504
8505 /* Block bitmap is on a bad block */
8506 { PR_1_BB_BAD_BLOCK,
8507 N_("@g %g's @b @B (%b) is bad. "),
8508 PROMPT_RELOCATE, 0 },
8509
8510 /* Inode bitmap is on a bad block */
8511 { PR_1_IB_BAD_BLOCK,
8512 N_("@g %g's @i @B (%b) is bad. "),
8513 PROMPT_RELOCATE, 0 },
8514
8515 /* Inode has incorrect i_size */
8516 { PR_1_BAD_I_SIZE,
8517 N_("@i %i, i_size is %Is, @s %N. "),
8518 PROMPT_FIX, PR_PREEN_OK },
8519
8520 /* Inode has incorrect i_blocks */
8521 { PR_1_BAD_I_BLOCKS,
8522 N_("@i %i, i_@bs is %Ib, @s %N. "),
8523 PROMPT_FIX, PR_PREEN_OK },
8524
8525 /* Illegal blocknumber in inode */
8526 { PR_1_ILLEGAL_BLOCK_NUM,
8527 N_("@I @b #%B (%b) in @i %i. "),
8528 PROMPT_CLEAR, PR_LATCH_BLOCK },
8529
8530 /* Block number overlaps fs metadata */
8531 { PR_1_BLOCK_OVERLAPS_METADATA,
8532 N_("@b #%B (%b) overlaps @f metadata in @i %i. "),
8533 PROMPT_CLEAR, PR_LATCH_BLOCK },
8534
8535 /* Inode has illegal blocks (latch question) */
8536 { PR_1_INODE_BLOCK_LATCH,
8537 N_("@i %i has illegal @b(s). "),
8538 PROMPT_CLEAR, 0 },
8539
8540 /* Too many bad blocks in inode */
8541 { PR_1_TOO_MANY_BAD_BLOCKS,
8542 N_("Too many illegal @bs in @i %i.\n"),
8543 PROMPT_CLEAR_INODE, PR_NO_OK },
8544
8545 /* Illegal block number in bad block inode */
8546 { PR_1_BB_ILLEGAL_BLOCK_NUM,
8547 N_("@I @b #%B (%b) in bad @b @i. "),
8548 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8549
8550 /* Bad block inode has illegal blocks (latch question) */
8551 { PR_1_INODE_BBLOCK_LATCH,
8552 N_("Bad @b @i has illegal @b(s). "),
8553 PROMPT_CLEAR, 0 },
8554
8555 /* Duplicate or bad blocks in use! */
8556 { PR_1_DUP_BLOCKS_PREENSTOP,
8557 N_("Duplicate or bad @b in use!\n"),
8558 PROMPT_NONE, 0 },
8559
8560 /* Bad block used as bad block indirect block */
8561 { PR_1_BBINODE_BAD_METABLOCK,
8562 N_("Bad @b %b used as bad @b @i indirect @b. "),
8563 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8564
8565 /* Inconsistency can't be fixed prompt */
8566 { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
8567 N_("\nThe bad @b @i has probably been corrupted. You probably\n"
8568 "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
8569 "in the @f.\n"),
8570 PROMPT_CONTINUE, PR_PREEN_NOMSG },
8571
8572 /* Bad primary block */
8573 { PR_1_BAD_PRIMARY_BLOCK,
8574 N_("\nIf the @b is really bad, the @f cannot be fixed.\n"),
8575 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
8576
8577 /* Bad primary block prompt */
8578 { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
8579 N_("You can remove this @b from the bad @b list and hope\n"
8580 "that the @b is really OK. But there are no guarantees.\n\n"),
8581 PROMPT_CLEAR, PR_PREEN_NOMSG },
8582
8583 /* Bad primary superblock */
8584 { PR_1_BAD_PRIMARY_SUPERBLOCK,
8585 N_("The primary @S (%b) is on the bad @b list.\n"),
8586 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8587
8588 /* Bad primary block group descriptors */
8589 { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
8590 N_("Block %b in the primary @g descriptors "
8591 "is on the bad @b list\n"),
8592 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8593
8594 /* Bad superblock in group */
8595 { PR_1_BAD_SUPERBLOCK,
8596 N_("Warning: Group %g's @S (%b) is bad.\n"),
8597 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8598
8599 /* Bad block group descriptors in group */
8600 { PR_1_BAD_GROUP_DESCRIPTORS,
8601 N_("Warning: Group %g's copy of the @g descriptors has a bad "
8602 "@b (%b).\n"),
8603 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8604
8605 /* Block claimed for no reason */
8606 { PR_1_PROGERR_CLAIMED_BLOCK,
8607 N_("Programming error? @b #%b claimed for no reason in "
8608 "process_bad_@b.\n"),
8609 PROMPT_NONE, PR_PREEN_OK },
8610
8611 /* Error allocating blocks for relocating metadata */
8612 { PR_1_RELOC_BLOCK_ALLOCATE,
8613 N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
8614 PROMPT_NONE, PR_PREEN_OK },
8615
8616 /* Error allocating block buffer during relocation process */
8617 { PR_1_RELOC_MEMORY_ALLOCATE,
8618 N_("@A @b buffer for relocating %s\n"),
8619 PROMPT_NONE, PR_PREEN_OK },
8620
8621 /* Relocating metadata group information from X to Y */
8622 { PR_1_RELOC_FROM_TO,
8623 N_("Relocating @g %g's %s from %b to %c...\n"),
8624 PROMPT_NONE, PR_PREEN_OK },
8625
8626 /* Relocating metatdata group information to X */
8627 { PR_1_RELOC_TO,
8628 N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
8629 PROMPT_NONE, PR_PREEN_OK },
8630
8631 /* Block read error during relocation process */
8632 { PR_1_RELOC_READ_ERR,
8633 N_("Warning: could not read @b %b of %s: %m\n"),
8634 PROMPT_NONE, PR_PREEN_OK },
8635
8636 /* Block write error during relocation process */
8637 { PR_1_RELOC_WRITE_ERR,
8638 N_("Warning: could not write @b %b for %s: %m\n"),
8639 PROMPT_NONE, PR_PREEN_OK },
8640
8641 /* Error allocating inode bitmap */
8642 { PR_1_ALLOCATE_IBITMAP_ERROR,
8643 N_("@A @i @B (%N): %m\n"),
8644 PROMPT_NONE, PR_FATAL },
8645
8646 /* Error allocating block bitmap */
8647 { PR_1_ALLOCATE_BBITMAP_ERROR,
8648 N_("@A @b @B (%N): %m\n"),
8649 PROMPT_NONE, PR_FATAL },
8650
8651 /* Error allocating icount structure */
8652 { PR_1_ALLOCATE_ICOUNT,
8653 N_("@A icount link information: %m\n"),
8654 PROMPT_NONE, PR_FATAL },
8655
8656 /* Error allocating dbcount */
8657 { PR_1_ALLOCATE_DBCOUNT,
8658 N_("@A @d @b array: %m\n"),
8659 PROMPT_NONE, PR_FATAL },
8660
8661 /* Error while scanning inodes */
8662 { PR_1_ISCAN_ERROR,
8663 N_("Error while scanning @is (%i): %m\n"),
8664 PROMPT_NONE, PR_FATAL },
8665
8666 /* Error while iterating over blocks */
8667 { PR_1_BLOCK_ITERATE,
8668 N_("Error while iterating over @bs in @i %i: %m\n"),
8669 PROMPT_NONE, PR_FATAL },
8670
8671 /* Error while storing inode count information */
8672 { PR_1_ICOUNT_STORE,
8673 N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
8674 PROMPT_NONE, PR_FATAL },
8675
8676 /* Error while storing directory block information */
8677 { PR_1_ADD_DBLOCK,
8678 N_("Error storing @d @b information "
8679 "(@i=%i, @b=%b, num=%N): %m\n"),
8680 PROMPT_NONE, PR_FATAL },
8681
8682 /* Error while reading inode (for clearing) */
8683 { PR_1_READ_INODE,
8684 N_("Error reading @i %i: %m\n"),
8685 PROMPT_NONE, PR_FATAL },
8686
8687 /* Suppress messages prompt */
8688 { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
8689
8690 /* Imagic flag set on an inode when filesystem doesn't support it */
8691 { PR_1_SET_IMAGIC,
8692 N_("@i %i has imagic flag set. "),
8693 PROMPT_CLEAR, 0 },
8694
8695 /* Immutable flag set on a device or socket inode */
8696 { PR_1_SET_IMMUTABLE,
8697 N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
8698 "or append-only flag set. "),
8699 PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
8700
8701 /* Compression flag set on an inode when filesystem doesn't support it */
8702 { PR_1_COMPR_SET,
8703 N_("@i %i has @cion flag set on @f without @cion support. "),
8704 PROMPT_CLEAR, 0 },
8705
8706 /* Non-zero size for device, fifo or socket inode */
8707 { PR_1_SET_NONZSIZE,
8708 N_("Special (@v/socket/fifo) @i %i has non-zero size. "),
8709 PROMPT_FIX, PR_PREEN_OK },
8710
8711 /* Filesystem revision is 0, but feature flags are set */
8712 { PR_1_FS_REV_LEVEL,
8713 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8714 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8715
8716 /* Journal inode is not in use, but contains data */
8717 { PR_1_JOURNAL_INODE_NOT_CLEAR,
8718 N_("@j @i is not in use, but contains data. "),
8719 PROMPT_CLEAR, PR_PREEN_OK },
8720
8721 /* Journal has bad mode */
8722 { PR_1_JOURNAL_BAD_MODE,
8723 N_("@j is not regular file. "),
8724 PROMPT_FIX, PR_PREEN_OK },
8725
8726 /* Deal with inodes that were part of orphan linked list */
8727 { PR_1_LOW_DTIME,
8728 N_("@i %i was part of the @o @i list. "),
8729 PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
8730
8731 /* Deal with inodes that were part of corrupted orphan linked
8732 list (latch question) */
8733 { PR_1_ORPHAN_LIST_REFUGEES,
8734 N_("@is that were part of a corrupted orphan linked list found. "),
8735 PROMPT_FIX, 0 },
8736
8737 /* Error allocating refcount structure */
8738 { PR_1_ALLOCATE_REFCOUNT,
8739 N_("@A refcount structure (%N): %m\n"),
8740 PROMPT_NONE, PR_FATAL },
8741
8742 /* Error reading extended attribute block */
8743 { PR_1_READ_EA_BLOCK,
8744 N_("Error reading @a @b %b for @i %i. "),
8745 PROMPT_CLEAR, 0 },
8746
8747 /* Invalid extended attribute block */
8748 { PR_1_BAD_EA_BLOCK,
8749 N_("@i %i has a bad @a @b %b. "),
8750 PROMPT_CLEAR, 0 },
8751
8752 /* Error reading Extended Attribute block while fixing refcount */
8753 { PR_1_EXTATTR_READ_ABORT,
8754 N_("Error reading @a @b %b (%m). "),
8755 PROMPT_ABORT, 0 },
8756
8757 /* Extended attribute reference count incorrect */
8758 { PR_1_EXTATTR_REFCOUNT,
8759 N_("@a @b %b has reference count %B, @s %N. "),
8760 PROMPT_FIX, 0 },
8761
8762 /* Error writing Extended Attribute block while fixing refcount */
8763 { PR_1_EXTATTR_WRITE,
8764 N_("Error writing @a @b %b (%m). "),
8765 PROMPT_ABORT, 0 },
8766
8767 /* Multiple EA blocks not supported */
8768 { PR_1_EA_MULTI_BLOCK,
8769 N_("@a @b %b has h_@bs > 1. "),
8770 PROMPT_CLEAR, 0},
8771
8772 /* Error allocating EA region allocation structure */
8773 { PR_1_EA_ALLOC_REGION,
8774 N_("@A @a @b %b. "),
8775 PROMPT_ABORT, 0},
8776
8777 /* Error EA allocation collision */
8778 { PR_1_EA_ALLOC_COLLISION,
8779 N_("@a @b %b is corrupt (allocation collision). "),
8780 PROMPT_CLEAR, 0},
8781
8782 /* Bad extended attribute name */
8783 { PR_1_EA_BAD_NAME,
8784 N_("@a @b %b is corrupt (@n name). "),
8785 PROMPT_CLEAR, 0},
8786
8787 /* Bad extended attribute value */
8788 { PR_1_EA_BAD_VALUE,
8789 N_("@a @b %b is corrupt (@n value). "),
8790 PROMPT_CLEAR, 0},
8791
8792 /* Inode too big (latch question) */
8793 { PR_1_INODE_TOOBIG,
8794 N_("@i %i is too big. "), PROMPT_TRUNCATE, 0 },
8795
8796 /* Directory too big */
8797 { PR_1_TOOBIG_DIR,
8798 N_("@b #%B (%b) causes @d to be too big. "),
8799 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8800
8801 /* Regular file too big */
8802 { PR_1_TOOBIG_REG,
8803 N_("@b #%B (%b) causes file to be too big. "),
8804 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8805
8806 /* Symlink too big */
8807 { PR_1_TOOBIG_SYMLINK,
8808 N_("@b #%B (%b) causes symlink to be too big. "),
8809 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8810
8811 /* INDEX_FL flag set on a non-HTREE filesystem */
8812 { PR_1_HTREE_SET,
8813 N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
8814 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8815
8816 /* INDEX_FL flag set on a non-directory */
8817 { PR_1_HTREE_NODIR,
8818 N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
8819 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8820
8821 /* Invalid root node in HTREE directory */
8822 { PR_1_HTREE_BADROOT,
8823 N_("@h %i has an @n root node.\n"),
8824 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8825
8826 /* Unsupported hash version in HTREE directory */
8827 { PR_1_HTREE_HASHV,
8828 N_("@h %i has an unsupported hash version (%N)\n"),
8829 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8830
8831 /* Incompatible flag in HTREE root node */
8832 { PR_1_HTREE_INCOMPAT,
8833 N_("@h %i uses an incompatible htree root node flag.\n"),
8834 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8835
8836 /* HTREE too deep */
8837 { PR_1_HTREE_DEPTH,
8838 N_("@h %i has a tree depth (%N) which is too big\n"),
8839 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8840
8841 /* Bad block has indirect block that conflicts with filesystem block */
8842 { PR_1_BB_FS_BLOCK,
8843 N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
8844 "@f metadata. "),
8845 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8846
8847 /* Resize inode failed */
8848 { PR_1_RESIZE_INODE_CREATE,
8849 N_("Resize @i (re)creation failed: %m."),
8850 PROMPT_ABORT, 0 },
8851
8852 /* invalid inode->i_extra_isize */
8853 { PR_1_EXTRA_ISIZE,
8854 N_("@i %i has a extra size (%IS) which is @n\n"),
8855 PROMPT_FIX, PR_PREEN_OK },
8856
8857 /* invalid ea entry->e_name_len */
8858 { PR_1_ATTR_NAME_LEN,
8859 N_("@a in @i %i has a namelen (%N) which is @n\n"),
8860 PROMPT_CLEAR, PR_PREEN_OK },
8861
8862 /* invalid ea entry->e_value_size */
8863 { PR_1_ATTR_VALUE_SIZE,
8864 N_("@a in @i %i has a value size (%N) which is @n\n"),
8865 PROMPT_CLEAR, PR_PREEN_OK },
8866
8867 /* invalid ea entry->e_value_offs */
8868 { PR_1_ATTR_VALUE_OFFSET,
8869 N_("@a in @i %i has a value offset (%N) which is @n\n"),
8870 PROMPT_CLEAR, PR_PREEN_OK },
8871
8872 /* invalid ea entry->e_value_block */
8873 { PR_1_ATTR_VALUE_BLOCK,
8874 N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
8875 PROMPT_CLEAR, PR_PREEN_OK },
8876
8877 /* invalid ea entry->e_hash */
8878 { PR_1_ATTR_HASH,
8879 N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
8880 PROMPT_CLEAR, PR_PREEN_OK },
8881
8882 /* Pass 1b errors */
8883
8884 /* Pass 1B: Rescan for duplicate/bad blocks */
8885 { PR_1B_PASS_HEADER,
8886 N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
8887 "Pass 1B: Rescanning for @m @bs\n"),
8888 PROMPT_NONE, 0 },
8889
8890 /* Duplicate/bad block(s) header */
8891 { PR_1B_DUP_BLOCK_HEADER,
8892 N_("@m @b(s) in @i %i:"),
8893 PROMPT_NONE, 0 },
8894
8895 /* Duplicate/bad block(s) in inode */
8896 { PR_1B_DUP_BLOCK,
8897 " %b",
8898 PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
8899
8900 /* Duplicate/bad block(s) end */
8901 { PR_1B_DUP_BLOCK_END,
8902 "\n",
8903 PROMPT_NONE, PR_PREEN_NOHDR },
8904
8905 /* Error while scanning inodes */
8906 { PR_1B_ISCAN_ERROR,
8907 N_("Error while scanning inodes (%i): %m\n"),
8908 PROMPT_NONE, PR_FATAL },
8909
8910 /* Error allocating inode bitmap */
8911 { PR_1B_ALLOCATE_IBITMAP_ERROR,
8912 N_("@A @i @B (@i_dup_map): %m\n"),
8913 PROMPT_NONE, PR_FATAL },
8914
8915 /* Error while iterating over blocks */
8916 { PR_1B_BLOCK_ITERATE,
8917 N_("Error while iterating over @bs in @i %i (%s): %m\n"),
8918 PROMPT_NONE, 0 },
8919
8920 /* Error adjusting EA refcount */
8921 { PR_1B_ADJ_EA_REFCOUNT,
8922 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
8923 PROMPT_NONE, 0 },
8924
8925
8926 /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
8927 { PR_1C_PASS_HEADER,
8928 N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
8929 PROMPT_NONE, 0 },
8930
8931
8932 /* Pass 1D: Reconciling multiply-claimed blocks */
8933 { PR_1D_PASS_HEADER,
8934 N_("Pass 1D: Reconciling @m @bs\n"),
8935 PROMPT_NONE, 0 },
8936
8937 /* File has duplicate blocks */
8938 { PR_1D_DUP_FILE,
8939 N_("File %Q (@i #%i, mod time %IM)\n"
8940 " has %B @m @b(s), shared with %N file(s):\n"),
8941 PROMPT_NONE, 0 },
8942
8943 /* List of files sharing duplicate blocks */
8944 { PR_1D_DUP_FILE_LIST,
8945 N_("\t%Q (@i #%i, mod time %IM)\n"),
8946 PROMPT_NONE, 0 },
8947
8948 /* File sharing blocks with filesystem metadata */
8949 { PR_1D_SHARE_METADATA,
8950 N_("\t<@f metadata>\n"),
8951 PROMPT_NONE, 0 },
8952
8953 /* Report of how many duplicate/bad inodes */
8954 { PR_1D_NUM_DUP_INODES,
8955 N_("(There are %N @is containing @m @bs.)\n\n"),
8956 PROMPT_NONE, 0 },
8957
8958 /* Duplicated blocks already reassigned or cloned. */
8959 { PR_1D_DUP_BLOCKS_DEALT,
8960 N_("@m @bs already reassigned or cloned.\n\n"),
8961 PROMPT_NONE, 0 },
8962
8963 /* Clone duplicate/bad blocks? */
8964 { PR_1D_CLONE_QUESTION,
8965 "", PROMPT_CLONE, PR_NO_OK },
8966
8967 /* Delete file? */
8968 { PR_1D_DELETE_QUESTION,
8969 "", PROMPT_DELETE, 0 },
8970
8971 /* Couldn't clone file (error) */
8972 { PR_1D_CLONE_ERROR,
8973 N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
8974
8975 /* Pass 2 errors */
8976
8977 /* Pass 2: Checking directory structure */
8978 { PR_2_PASS_HEADER,
8979 N_("Pass 2: Checking @d structure\n"),
8980 PROMPT_NONE, 0 },
8981
8982 /* Bad inode number for '.' */
8983 { PR_2_BAD_INODE_DOT,
8984 N_("@n @i number for '.' in @d @i %i.\n"),
8985 PROMPT_FIX, 0 },
8986
8987 /* Directory entry has bad inode number */
8988 { PR_2_BAD_INO,
8989 N_("@E has @n @i #: %Di.\n"),
8990 PROMPT_CLEAR, 0 },
8991
8992 /* Directory entry has deleted or unused inode */
8993 { PR_2_UNUSED_INODE,
8994 N_("@E has @D/unused @i %Di. "),
8995 PROMPT_CLEAR, PR_PREEN_OK },
8996
8997 /* Directry entry is link to '.' */
8998 { PR_2_LINK_DOT,
8999 N_("@E @L to '.' "),
9000 PROMPT_CLEAR, 0 },
9001
9002 /* Directory entry points to inode now located in a bad block */
9003 { PR_2_BB_INODE,
9004 N_("@E points to @i (%Di) located in a bad @b.\n"),
9005 PROMPT_CLEAR, 0 },
9006
9007 /* Directory entry contains a link to a directory */
9008 { PR_2_LINK_DIR,
9009 N_("@E @L to @d %P (%Di).\n"),
9010 PROMPT_CLEAR, 0 },
9011
9012 /* Directory entry contains a link to the root directry */
9013 { PR_2_LINK_ROOT,
9014 N_("@E @L to the @r.\n"),
9015 PROMPT_CLEAR, 0 },
9016
9017 /* Directory entry has illegal characters in its name */
9018 { PR_2_BAD_NAME,
9019 N_("@E has illegal characters in its name.\n"),
9020 PROMPT_FIX, 0 },
9021
9022 /* Missing '.' in directory inode */
9023 { PR_2_MISSING_DOT,
9024 N_("Missing '.' in @d @i %i.\n"),
9025 PROMPT_FIX, 0 },
9026
9027 /* Missing '..' in directory inode */
9028 { PR_2_MISSING_DOT_DOT,
9029 N_("Missing '..' in @d @i %i.\n"),
9030 PROMPT_FIX, 0 },
9031
9032 /* First entry in directory inode doesn't contain '.' */
9033 { PR_2_1ST_NOT_DOT,
9034 N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
9035 PROMPT_FIX, 0 },
9036
9037 /* Second entry in directory inode doesn't contain '..' */
9038 { PR_2_2ND_NOT_DOT_DOT,
9039 N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
9040 PROMPT_FIX, 0 },
9041
9042 /* i_faddr should be zero */
9043 { PR_2_FADDR_ZERO,
9044 N_("i_faddr @F %IF, @s zero.\n"),
9045 PROMPT_CLEAR, 0 },
9046
9047 /* i_file_acl should be zero */
9048 { PR_2_FILE_ACL_ZERO,
9049 N_("i_file_acl @F %If, @s zero.\n"),
9050 PROMPT_CLEAR, 0 },
9051
9052 /* i_dir_acl should be zero */
9053 { PR_2_DIR_ACL_ZERO,
9054 N_("i_dir_acl @F %Id, @s zero.\n"),
9055 PROMPT_CLEAR, 0 },
9056
9057 /* i_frag should be zero */
9058 { PR_2_FRAG_ZERO,
9059 N_("i_frag @F %N, @s zero.\n"),
9060 PROMPT_CLEAR, 0 },
9061
9062 /* i_fsize should be zero */
9063 { PR_2_FSIZE_ZERO,
9064 N_("i_fsize @F %N, @s zero.\n"),
9065 PROMPT_CLEAR, 0 },
9066
9067 /* inode has bad mode */
9068 { PR_2_BAD_MODE,
9069 N_("@i %i (%Q) has @n mode (%Im).\n"),
9070 PROMPT_CLEAR, 0 },
9071
9072 /* directory corrupted */
9073 { PR_2_DIR_CORRUPTED,
9074 N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
9075 PROMPT_SALVAGE, 0 },
9076
9077 /* filename too long */
9078 { PR_2_FILENAME_LONG,
9079 N_("@d @i %i, @b %B, offset %N: filename too long\n"),
9080 PROMPT_TRUNCATE, 0 },
9081
9082 /* Directory inode has a missing block (hole) */
9083 { PR_2_DIRECTORY_HOLE,
9084 N_("@d @i %i has an unallocated @b #%B. "),
9085 PROMPT_ALLOCATE, 0 },
9086
9087 /* '.' is not NULL terminated */
9088 { PR_2_DOT_NULL_TERM,
9089 N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
9090 PROMPT_FIX, 0 },
9091
9092 /* '..' is not NULL terminated */
9093 { PR_2_DOT_DOT_NULL_TERM,
9094 N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
9095 PROMPT_FIX, 0 },
9096
9097 /* Illegal character device inode */
9098 { PR_2_BAD_CHAR_DEV,
9099 N_("@i %i (%Q) is an @I character @v.\n"),
9100 PROMPT_CLEAR, 0 },
9101
9102 /* Illegal block device inode */
9103 { PR_2_BAD_BLOCK_DEV,
9104 N_("@i %i (%Q) is an @I @b @v.\n"),
9105 PROMPT_CLEAR, 0 },
9106
9107 /* Duplicate '.' entry */
9108 { PR_2_DUP_DOT,
9109 N_("@E is duplicate '.' @e.\n"),
9110 PROMPT_FIX, 0 },
9111
9112 /* Duplicate '..' entry */
9113 { PR_2_DUP_DOT_DOT,
9114 N_("@E is duplicate '..' @e.\n"),
9115 PROMPT_FIX, 0 },
9116
9117 /* Internal error: couldn't find dir_info */
9118 { PR_2_NO_DIRINFO,
9119 N_("Internal error: cannot find dir_info for %i.\n"),
9120 PROMPT_NONE, PR_FATAL },
9121
9122 /* Final rec_len is wrong */
9123 { PR_2_FINAL_RECLEN,
9124 N_("@E has rec_len of %Dr, @s %N.\n"),
9125 PROMPT_FIX, 0 },
9126
9127 /* Error allocating icount structure */
9128 { PR_2_ALLOCATE_ICOUNT,
9129 N_("@A icount structure: %m\n"),
9130 PROMPT_NONE, PR_FATAL },
9131
9132 /* Error iterating over directory blocks */
9133 { PR_2_DBLIST_ITERATE,
9134 N_("Error iterating over @d @bs: %m\n"),
9135 PROMPT_NONE, PR_FATAL },
9136
9137 /* Error reading directory block */
9138 { PR_2_READ_DIRBLOCK,
9139 N_("Error reading @d @b %b (@i %i): %m\n"),
9140 PROMPT_CONTINUE, 0 },
9141
9142 /* Error writing directory block */
9143 { PR_2_WRITE_DIRBLOCK,
9144 N_("Error writing @d @b %b (@i %i): %m\n"),
9145 PROMPT_CONTINUE, 0 },
9146
9147 /* Error allocating new directory block */
9148 { PR_2_ALLOC_DIRBOCK,
9149 N_("@A new @d @b for @i %i (%s): %m\n"),
9150 PROMPT_NONE, 0 },
9151
9152 /* Error deallocating inode */
9153 { PR_2_DEALLOC_INODE,
9154 N_("Error deallocating @i %i: %m\n"),
9155 PROMPT_NONE, PR_FATAL },
9156
9157 /* Directory entry for '.' is big. Split? */
9158 { PR_2_SPLIT_DOT,
9159 N_("@d @e for '.' is big. "),
9160 PROMPT_SPLIT, PR_NO_OK },
9161
9162 /* Illegal FIFO inode */
9163 { PR_2_BAD_FIFO,
9164 N_("@i %i (%Q) is an @I FIFO.\n"),
9165 PROMPT_CLEAR, 0 },
9166
9167 /* Illegal socket inode */
9168 { PR_2_BAD_SOCKET,
9169 N_("@i %i (%Q) is an @I socket.\n"),
9170 PROMPT_CLEAR, 0 },
9171
9172 /* Directory filetype not set */
9173 { PR_2_SET_FILETYPE,
9174 N_("Setting filetype for @E to %N.\n"),
9175 PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
9176
9177 /* Directory filetype incorrect */
9178 { PR_2_BAD_FILETYPE,
9179 N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
9180 PROMPT_FIX, 0 },
9181
9182 /* Directory filetype set on filesystem */
9183 { PR_2_CLEAR_FILETYPE,
9184 N_("@E has filetype set.\n"),
9185 PROMPT_CLEAR, PR_PREEN_OK },
9186
9187 /* Directory filename is null */
9188 { PR_2_NULL_NAME,
9189 N_("@E has a @z name.\n"),
9190 PROMPT_CLEAR, 0 },
9191
9192 /* Invalid symlink */
9193 { PR_2_INVALID_SYMLINK,
9194 N_("Symlink %Q (@i #%i) is @n.\n"),
9195 PROMPT_CLEAR, 0 },
9196
9197 /* i_file_acl (extended attribute block) is bad */
9198 { PR_2_FILE_ACL_BAD,
9199 N_("@a @b @F @n (%If).\n"),
9200 PROMPT_CLEAR, 0 },
9201
9202 /* Filesystem contains large files, but has no such flag in sb */
9203 { PR_2_FEATURE_LARGE_FILES,
9204 N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
9205 PROMPT_FIX, 0 },
9206
9207 /* Node in HTREE directory not referenced */
9208 { PR_2_HTREE_NOTREF,
9209 N_("@p @h %d: node (%B) not referenced\n"),
9210 PROMPT_NONE, 0 },
9211
9212 /* Node in HTREE directory referenced twice */
9213 { PR_2_HTREE_DUPREF,
9214 N_("@p @h %d: node (%B) referenced twice\n"),
9215 PROMPT_NONE, 0 },
9216
9217 /* Node in HTREE directory has bad min hash */
9218 { PR_2_HTREE_MIN_HASH,
9219 N_("@p @h %d: node (%B) has bad min hash\n"),
9220 PROMPT_NONE, 0 },
9221
9222 /* Node in HTREE directory has bad max hash */
9223 { PR_2_HTREE_MAX_HASH,
9224 N_("@p @h %d: node (%B) has bad max hash\n"),
9225 PROMPT_NONE, 0 },
9226
9227 /* Clear invalid HTREE directory */
9228 { PR_2_HTREE_CLEAR,
9229 N_("@n @h %d (%q). "), PROMPT_CLEAR, 0 },
9230
9231 /* Bad block in htree interior node */
9232 { PR_2_HTREE_BADBLK,
9233 N_("@p @h %d (%q): bad @b number %b.\n"),
9234 PROMPT_CLEAR_HTREE, 0 },
9235
9236 /* Error adjusting EA refcount */
9237 { PR_2_ADJ_EA_REFCOUNT,
9238 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
9239 PROMPT_NONE, PR_FATAL },
9240
9241 /* Invalid HTREE root node */
9242 { PR_2_HTREE_BAD_ROOT,
9243 N_("@p @h %d: root node is @n\n"),
9244 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9245
9246 /* Invalid HTREE limit */
9247 { PR_2_HTREE_BAD_LIMIT,
9248 N_("@p @h %d: node (%B) has @n limit (%N)\n"),
9249 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9250
9251 /* Invalid HTREE count */
9252 { PR_2_HTREE_BAD_COUNT,
9253 N_("@p @h %d: node (%B) has @n count (%N)\n"),
9254 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9255
9256 /* HTREE interior node has out-of-order hashes in table */
9257 { PR_2_HTREE_HASH_ORDER,
9258 N_("@p @h %d: node (%B) has an unordered hash table\n"),
9259 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9260
9261 /* Node in HTREE directory has invalid depth */
9262 { PR_2_HTREE_BAD_DEPTH,
9263 N_("@p @h %d: node (%B) has @n depth\n"),
9264 PROMPT_NONE, 0 },
9265
9266 /* Duplicate directory entry found */
9267 { PR_2_DUPLICATE_DIRENT,
9268 N_("Duplicate @E found. "),
9269 PROMPT_CLEAR, 0 },
9270
9271 /* Non-unique filename found */
9272 { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
9273 N_("@E has a non-unique filename.\nRename to %s"),
9274 PROMPT_NULL, 0 },
9275
9276 /* Duplicate directory entry found */
9277 { PR_2_REPORT_DUP_DIRENT,
9278 N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
9279 PROMPT_NONE, 0 },
9280
9281 /* Pass 3 errors */
9282
9283 /* Pass 3: Checking directory connectivity */
9284 { PR_3_PASS_HEADER,
9285 N_("Pass 3: Checking @d connectivity\n"),
9286 PROMPT_NONE, 0 },
9287
9288 /* Root inode not allocated */
9289 { PR_3_NO_ROOT_INODE,
9290 N_("@r not allocated. "),
9291 PROMPT_ALLOCATE, 0 },
9292
9293 /* No room in lost+found */
9294 { PR_3_EXPAND_LF_DIR,
9295 N_("No room in @l @d. "),
9296 PROMPT_EXPAND, 0 },
9297
9298 /* Unconnected directory inode */
9299 { PR_3_UNCONNECTED_DIR,
9300 N_("Unconnected @d @i %i (%p)\n"),
9301 PROMPT_CONNECT, 0 },
9302
9303 /* /lost+found not found */
9304 { PR_3_NO_LF_DIR,
9305 N_("/@l not found. "),
9306 PROMPT_CREATE, PR_PREEN_OK },
9307
9308 /* .. entry is incorrect */
9309 { PR_3_BAD_DOT_DOT,
9310 N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
9311 PROMPT_FIX, 0 },
9312
9313 /* Bad or non-existent /lost+found. Cannot reconnect */
9314 { PR_3_NO_LPF,
9315 N_("Bad or non-existent /@l. Cannot reconnect.\n"),
9316 PROMPT_NONE, 0 },
9317
9318 /* Could not expand /lost+found */
9319 { PR_3_CANT_EXPAND_LPF,
9320 N_("Could not expand /@l: %m\n"),
9321 PROMPT_NONE, 0 },
9322
9323 /* Could not reconnect inode */
9324 { PR_3_CANT_RECONNECT,
9325 N_("Could not reconnect %i: %m\n"),
9326 PROMPT_NONE, 0 },
9327
9328 /* Error while trying to find /lost+found */
9329 { PR_3_ERR_FIND_LPF,
9330 N_("Error while trying to find /@l: %m\n"),
9331 PROMPT_NONE, 0 },
9332
9333 /* Error in ext2fs_new_block while creating /lost+found */
9334 { PR_3_ERR_LPF_NEW_BLOCK,
9335 N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
9336 PROMPT_NONE, 0 },
9337
9338 /* Error in ext2fs_new_inode while creating /lost+found */
9339 { PR_3_ERR_LPF_NEW_INODE,
9340 N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
9341 PROMPT_NONE, 0 },
9342
9343 /* Error in ext2fs_new_dir_block while creating /lost+found */
9344 { PR_3_ERR_LPF_NEW_DIR_BLOCK,
9345 N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
9346 PROMPT_NONE, 0 },
9347
9348 /* Error while writing directory block for /lost+found */
9349 { PR_3_ERR_LPF_WRITE_BLOCK,
9350 N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
9351 PROMPT_NONE, 0 },
9352
9353 /* Error while adjusting inode count */
9354 { PR_3_ADJUST_INODE,
9355 N_("Error while adjusting @i count on @i %i\n"),
9356 PROMPT_NONE, 0 },
9357
9358 /* Couldn't fix parent directory -- error */
9359 { PR_3_FIX_PARENT_ERR,
9360 N_("Couldn't fix parent of @i %i: %m\n\n"),
9361 PROMPT_NONE, 0 },
9362
9363 /* Couldn't fix parent directory -- couldn't find it */
9364 { PR_3_FIX_PARENT_NOFIND,
9365 N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
9366 PROMPT_NONE, 0 },
9367
9368 /* Error allocating inode bitmap */
9369 { PR_3_ALLOCATE_IBITMAP_ERROR,
9370 N_("@A @i @B (%N): %m\n"),
9371 PROMPT_NONE, PR_FATAL },
9372
9373 /* Error creating root directory */
9374 { PR_3_CREATE_ROOT_ERROR,
9375 N_("Error creating root @d (%s): %m\n"),
9376 PROMPT_NONE, PR_FATAL },
9377
9378 /* Error creating lost and found directory */
9379 { PR_3_CREATE_LPF_ERROR,
9380 N_("Error creating /@l @d (%s): %m\n"),
9381 PROMPT_NONE, PR_FATAL },
9382
9383 /* Root inode is not directory; aborting */
9384 { PR_3_ROOT_NOT_DIR_ABORT,
9385 N_("@r is not a @d; aborting.\n"),
9386 PROMPT_NONE, PR_FATAL },
9387
9388 /* Cannot proceed without a root inode. */
9389 { PR_3_NO_ROOT_INODE_ABORT,
Denys Vlasenko6331cf02009-11-13 09:08:27 +01009390 N_("can't proceed without a @r.\n"),
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00009391 PROMPT_NONE, PR_FATAL },
9392
9393 /* Internal error: couldn't find dir_info */
9394 { PR_3_NO_DIRINFO,
9395 N_("Internal error: cannot find dir_info for %i.\n"),
9396 PROMPT_NONE, PR_FATAL },
9397
9398 /* Lost+found not a directory */
9399 { PR_3_LPF_NOTDIR,
9400 N_("/@l is not a @d (ino=%i)\n"),
9401 PROMPT_UNLINK, 0 },
9402
9403 /* Pass 3A Directory Optimization */
9404
9405 /* Pass 3A: Optimizing directories */
9406 { PR_3A_PASS_HEADER,
9407 N_("Pass 3A: Optimizing directories\n"),
9408 PROMPT_NONE, PR_PREEN_NOMSG },
9409
9410 /* Error iterating over directories */
9411 { PR_3A_OPTIMIZE_ITER,
9412 N_("Failed to create dirs_to_hash iterator: %m"),
9413 PROMPT_NONE, 0 },
9414
9415 /* Error rehash directory */
9416 { PR_3A_OPTIMIZE_DIR_ERR,
9417 N_("Failed to optimize directory %q (%d): %m"),
9418 PROMPT_NONE, 0 },
9419
9420 /* Rehashing dir header */
9421 { PR_3A_OPTIMIZE_DIR_HEADER,
9422 N_("Optimizing directories: "),
9423 PROMPT_NONE, PR_MSG_ONLY },
9424
9425 /* Rehashing directory %d */
9426 { PR_3A_OPTIMIZE_DIR,
9427 " %d",
9428 PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
9429
9430 /* Rehashing dir end */
9431 { PR_3A_OPTIMIZE_DIR_END,
9432 "\n",
9433 PROMPT_NONE, PR_PREEN_NOHDR },
9434
9435 /* Pass 4 errors */
9436
9437 /* Pass 4: Checking reference counts */
9438 { PR_4_PASS_HEADER,
9439 N_("Pass 4: Checking reference counts\n"),
9440 PROMPT_NONE, 0 },
9441
9442 /* Unattached zero-length inode */
9443 { PR_4_ZERO_LEN_INODE,
9444 N_("@u @z @i %i. "),
9445 PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
9446
9447 /* Unattached inode */
9448 { PR_4_UNATTACHED_INODE,
9449 N_("@u @i %i\n"),
9450 PROMPT_CONNECT, 0 },
9451
9452 /* Inode ref count wrong */
9453 { PR_4_BAD_REF_COUNT,
9454 N_("@i %i ref count is %Il, @s %N. "),
9455 PROMPT_FIX, PR_PREEN_OK },
9456
9457 { PR_4_INCONSISTENT_COUNT,
9458 N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
9459 "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
9460 "@i_link_info[%i] is %N, @i.i_links_count is %Il. "
9461 "They @s the same!\n"),
9462 PROMPT_NONE, 0 },
9463
9464 /* Pass 5 errors */
9465
9466 /* Pass 5: Checking group summary information */
9467 { PR_5_PASS_HEADER,
9468 N_("Pass 5: Checking @g summary information\n"),
9469 PROMPT_NONE, 0 },
9470
9471 /* Padding at end of inode bitmap is not set. */
9472 { PR_5_INODE_BMAP_PADDING,
9473 N_("Padding at end of @i @B is not set. "),
9474 PROMPT_FIX, PR_PREEN_OK },
9475
9476 /* Padding at end of block bitmap is not set. */
9477 { PR_5_BLOCK_BMAP_PADDING,
9478 N_("Padding at end of @b @B is not set. "),
9479 PROMPT_FIX, PR_PREEN_OK },
9480
9481 /* Block bitmap differences header */
9482 { PR_5_BLOCK_BITMAP_HEADER,
9483 N_("@b @B differences: "),
9484 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
9485
9486 /* Block not used, but marked in bitmap */
9487 { PR_5_BLOCK_UNUSED,
9488 " -%b",
9489 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9490
9491 /* Block used, but not marked used in bitmap */
9492 { PR_5_BLOCK_USED,
9493 " +%b",
9494 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9495
9496 /* Block bitmap differences end */
9497 { PR_5_BLOCK_BITMAP_END,
9498 "\n",
9499 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9500
9501 /* Inode bitmap differences header */
9502 { PR_5_INODE_BITMAP_HEADER,
9503 N_("@i @B differences: "),
9504 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9505
9506 /* Inode not used, but marked in bitmap */
9507 { PR_5_INODE_UNUSED,
9508 " -%i",
9509 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9510
9511 /* Inode used, but not marked used in bitmap */
9512 { PR_5_INODE_USED,
9513 " +%i",
9514 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9515
9516 /* Inode bitmap differences end */
9517 { PR_5_INODE_BITMAP_END,
9518 "\n",
9519 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9520
9521 /* Free inodes count for group wrong */
9522 { PR_5_FREE_INODE_COUNT_GROUP,
9523 N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
9524 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9525
9526 /* Directories count for group wrong */
9527 { PR_5_FREE_DIR_COUNT_GROUP,
9528 N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
9529 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9530
9531 /* Free inodes count wrong */
9532 { PR_5_FREE_INODE_COUNT,
9533 N_("Free @is count wrong (%i, counted=%j).\n"),
9534 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9535
9536 /* Free blocks count for group wrong */
9537 { PR_5_FREE_BLOCK_COUNT_GROUP,
9538 N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
9539 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9540
9541 /* Free blocks count wrong */
9542 { PR_5_FREE_BLOCK_COUNT,
9543 N_("Free @bs count wrong (%b, counted=%c).\n"),
9544 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9545
9546 /* Programming error: bitmap endpoints don't match */
9547 { PR_5_BMAP_ENDPOINTS,
9548 N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
9549 "match calculated @B endpoints (%i, %j)\n"),
9550 PROMPT_NONE, PR_FATAL },
9551
9552 /* Internal error: fudging end of bitmap */
9553 { PR_5_FUDGE_BITMAP_ERROR,
9554 N_("Internal error: fudging end of bitmap (%N)\n"),
9555 PROMPT_NONE, PR_FATAL },
9556
9557 /* Error copying in replacement inode bitmap */
9558 { PR_5_COPY_IBITMAP_ERROR,
9559 N_("Error copying in replacement @i @B: %m\n"),
9560 PROMPT_NONE, PR_FATAL },
9561
9562 /* Error copying in replacement block bitmap */
9563 { PR_5_COPY_BBITMAP_ERROR,
9564 N_("Error copying in replacement @b @B: %m\n"),
9565 PROMPT_NONE, PR_FATAL },
9566
9567 /* Block range not used, but marked in bitmap */
9568 { PR_5_BLOCK_RANGE_UNUSED,
9569 " -(%b--%c)",
9570 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9571
9572 /* Block range used, but not marked used in bitmap */
9573 { PR_5_BLOCK_RANGE_USED,
9574 " +(%b--%c)",
9575 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9576
9577 /* Inode range not used, but marked in bitmap */
9578 { PR_5_INODE_RANGE_UNUSED,
9579 " -(%i--%j)",
9580 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9581
9582 /* Inode range used, but not marked used in bitmap */
9583 { PR_5_INODE_RANGE_USED,
9584 " +(%i--%j)",
9585 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9586
9587 { 0 }
9588};
9589
9590/*
9591 * This is the latch flags register. It allows several problems to be
9592 * "latched" together. This means that the user has to answer but one
9593 * question for the set of problems, and all of the associated
9594 * problems will be either fixed or not fixed.
9595 */
9596static struct latch_descr pr_latch_info[] = {
9597 { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
9598 { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
9599 { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
9600 { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
9601 { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
9602 { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
9603 { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
9604 { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
9605 { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
9606 { -1, 0, 0 },
9607};
9608
9609static const struct e2fsck_problem *find_problem(problem_t code)
9610{
9611 int i;
9612
9613 for (i=0; problem_table[i].e2p_code; i++) {
9614 if (problem_table[i].e2p_code == code)
9615 return &problem_table[i];
9616 }
9617 return 0;
9618}
9619
9620static struct latch_descr *find_latch(int code)
9621{
9622 int i;
9623
9624 for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
9625 if (pr_latch_info[i].latch_code == code)
9626 return &pr_latch_info[i];
9627 }
9628 return 0;
9629}
9630
9631int end_problem_latch(e2fsck_t ctx, int mask)
9632{
9633 struct latch_descr *ldesc;
9634 struct problem_context pctx;
9635 int answer = -1;
9636
9637 ldesc = find_latch(mask);
9638 if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
9639 clear_problem_context(&pctx);
9640 answer = fix_problem(ctx, ldesc->end_message, &pctx);
9641 }
9642 ldesc->flags &= ~(PRL_VARIABLE);
9643 return answer;
9644}
9645
9646int set_latch_flags(int mask, int setflags, int clearflags)
9647{
9648 struct latch_descr *ldesc;
9649
9650 ldesc = find_latch(mask);
9651 if (!ldesc)
9652 return -1;
9653 ldesc->flags |= setflags;
9654 ldesc->flags &= ~clearflags;
9655 return 0;
9656}
9657
9658void clear_problem_context(struct problem_context *ctx)
9659{
9660 memset(ctx, 0, sizeof(struct problem_context));
9661 ctx->blkcount = -1;
9662 ctx->group = -1;
9663}
9664
9665int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
9666{
9667 ext2_filsys fs = ctx->fs;
9668 const struct e2fsck_problem *ptr;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +01009669 struct latch_descr *ldesc = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00009670 const char *message;
9671 int def_yn, answer, ans;
9672 int print_answer = 0;
9673 int suppress = 0;
9674
9675 ptr = find_problem(code);
9676 if (!ptr) {
9677 printf(_("Unhandled error code (0x%x)!\n"), code);
9678 return 0;
9679 }
9680 def_yn = 1;
9681 if ((ptr->flags & PR_NO_DEFAULT) ||
9682 ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
9683 (ctx->options & E2F_OPT_NO))
9684 def_yn= 0;
9685
9686 /*
9687 * Do special latch processing. This is where we ask the
9688 * latch question, if it exists
9689 */
9690 if (ptr->flags & PR_LATCH_MASK) {
9691 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
9692 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
9693 ans = fix_problem(ctx, ldesc->question, pctx);
9694 if (ans == 1)
9695 ldesc->flags |= PRL_YES;
9696 if (ans == 0)
9697 ldesc->flags |= PRL_NO;
9698 ldesc->flags |= PRL_LATCHED;
9699 }
9700 if (ldesc->flags & PRL_SUPPRESS)
9701 suppress++;
9702 }
9703 if ((ptr->flags & PR_PREEN_NOMSG) &&
9704 (ctx->options & E2F_OPT_PREEN))
9705 suppress++;
9706 if ((ptr->flags & PR_NO_NOMSG) &&
9707 (ctx->options & E2F_OPT_NO))
9708 suppress++;
9709 if (!suppress) {
9710 message = ptr->e2p_description;
9711 if ((ctx->options & E2F_OPT_PREEN) &&
9712 !(ptr->flags & PR_PREEN_NOHDR)) {
9713 printf("%s: ", ctx->device_name ?
9714 ctx->device_name : ctx->filesystem_name);
9715 }
9716 if (*message)
9717 print_e2fsck_message(ctx, _(message), pctx, 1);
9718 }
9719 if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
9720 preenhalt(ctx);
9721
9722 if (ptr->flags & PR_FATAL)
9723 bb_error_msg_and_die(0);
9724
9725 if (ptr->prompt == PROMPT_NONE) {
9726 if (ptr->flags & PR_NOCOLLATE)
9727 answer = -1;
9728 else
9729 answer = def_yn;
9730 } else {
9731 if (ctx->options & E2F_OPT_PREEN) {
9732 answer = def_yn;
9733 if (!(ptr->flags & PR_PREEN_NOMSG))
9734 print_answer = 1;
9735 } else if ((ptr->flags & PR_LATCH_MASK) &&
9736 (ldesc->flags & (PRL_YES | PRL_NO))) {
9737 if (!suppress)
9738 print_answer = 1;
9739 if (ldesc->flags & PRL_YES)
9740 answer = 1;
9741 else
9742 answer = 0;
9743 } else
9744 answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
9745 if (!answer && !(ptr->flags & PR_NO_OK))
9746 ext2fs_unmark_valid(fs);
9747
9748 if (print_answer)
9749 printf("%s.\n", answer ?
9750 _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
9751
9752 }
9753
9754 if ((ptr->prompt == PROMPT_ABORT) && answer)
9755 bb_error_msg_and_die(0);
9756
9757 if (ptr->flags & PR_AFTER_CODE)
9758 answer = fix_problem(ctx, ptr->second_code, pctx);
9759
9760 return answer;
9761}
9762
9763/*
9764 * linux/fs/recovery.c
9765 *
9766 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
9767 */
9768
9769/*
9770 * Maintain information about the progress of the recovery job, so that
9771 * the different passes can carry information between them.
9772 */
9773struct recovery_info
9774{
9775 tid_t start_transaction;
9776 tid_t end_transaction;
9777
9778 int nr_replays;
9779 int nr_revokes;
9780 int nr_revoke_hits;
9781};
9782
9783enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
9784static int do_one_pass(journal_t *journal,
9785 struct recovery_info *info, enum passtype pass);
9786static int scan_revoke_records(journal_t *, struct buffer_head *,
9787 tid_t, struct recovery_info *);
9788
9789/*
9790 * Read a block from the journal
9791 */
9792
9793static int jread(struct buffer_head **bhp, journal_t *journal,
9794 unsigned int offset)
9795{
9796 int err;
9797 unsigned long blocknr;
9798 struct buffer_head *bh;
9799
9800 *bhp = NULL;
9801
9802 err = journal_bmap(journal, offset, &blocknr);
9803
9804 if (err) {
9805 printf("JBD: bad block at offset %u\n", offset);
9806 return err;
9807 }
9808
9809 bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
9810 if (!bh)
9811 return -ENOMEM;
9812
9813 if (!buffer_uptodate(bh)) {
9814 /* If this is a brand new buffer, start readahead.
9815 Otherwise, we assume we are already reading it. */
9816 if (!buffer_req(bh))
9817 do_readahead(journal, offset);
9818 wait_on_buffer(bh);
9819 }
9820
9821 if (!buffer_uptodate(bh)) {
9822 printf("JBD: Failed to read block at offset %u\n", offset);
9823 brelse(bh);
9824 return -EIO;
9825 }
9826
9827 *bhp = bh;
9828 return 0;
9829}
9830
9831
9832/*
9833 * Count the number of in-use tags in a journal descriptor block.
9834 */
9835
9836static int count_tags(struct buffer_head *bh, int size)
9837{
9838 char * tagp;
9839 journal_block_tag_t * tag;
9840 int nr = 0;
9841
9842 tagp = &bh->b_data[sizeof(journal_header_t)];
9843
9844 while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
9845 tag = (journal_block_tag_t *) tagp;
9846
9847 nr++;
9848 tagp += sizeof(journal_block_tag_t);
9849 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
9850 tagp += 16;
9851
9852 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
9853 break;
9854 }
9855
9856 return nr;
9857}
9858
9859
9860/* Make sure we wrap around the log correctly! */
9861#define wrap(journal, var) \
9862do { \
9863 if (var >= (journal)->j_last) \
9864 var -= ((journal)->j_last - (journal)->j_first); \
9865} while (0)
9866
9867/**
9868 * int journal_recover(journal_t *journal) - recovers a on-disk journal
9869 * @journal: the journal to recover
9870 *
9871 * The primary function for recovering the log contents when mounting a
9872 * journaled device.
9873 *
9874 * Recovery is done in three passes. In the first pass, we look for the
9875 * end of the log. In the second, we assemble the list of revoke
9876 * blocks. In the third and final pass, we replay any un-revoked blocks
9877 * in the log.
9878 */
9879int journal_recover(journal_t *journal)
9880{
9881 int err;
9882 journal_superblock_t * sb;
9883
9884 struct recovery_info info;
9885
9886 memset(&info, 0, sizeof(info));
9887 sb = journal->j_superblock;
9888
9889 /*
9890 * The journal superblock's s_start field (the current log head)
9891 * is always zero if, and only if, the journal was cleanly
9892 * unmounted.
9893 */
9894
9895 if (!sb->s_start) {
9896 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
9897 return 0;
9898 }
9899
9900 err = do_one_pass(journal, &info, PASS_SCAN);
9901 if (!err)
9902 err = do_one_pass(journal, &info, PASS_REVOKE);
9903 if (!err)
9904 err = do_one_pass(journal, &info, PASS_REPLAY);
9905
9906 /* Restart the log at the next transaction ID, thus invalidating
9907 * any existing commit records in the log. */
9908 journal->j_transaction_sequence = ++info.end_transaction;
9909
9910 journal_clear_revoke(journal);
9911 sync_blockdev(journal->j_fs_dev);
9912 return err;
9913}
9914
9915static int do_one_pass(journal_t *journal,
9916 struct recovery_info *info, enum passtype pass)
9917{
9918 unsigned int first_commit_ID, next_commit_ID;
9919 unsigned long next_log_block;
9920 int err, success = 0;
9921 journal_superblock_t * sb;
9922 journal_header_t * tmp;
9923 struct buffer_head * bh;
9924 unsigned int sequence;
9925 int blocktype;
9926
9927 /* Precompute the maximum metadata descriptors in a descriptor block */
9928 int MAX_BLOCKS_PER_DESC;
9929 MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
9930 / sizeof(journal_block_tag_t));
9931
9932 /*
9933 * First thing is to establish what we expect to find in the log
9934 * (in terms of transaction IDs), and where (in terms of log
9935 * block offsets): query the superblock.
9936 */
9937
9938 sb = journal->j_superblock;
9939 next_commit_ID = ntohl(sb->s_sequence);
9940 next_log_block = ntohl(sb->s_start);
9941
9942 first_commit_ID = next_commit_ID;
9943 if (pass == PASS_SCAN)
9944 info->start_transaction = first_commit_ID;
9945
9946 /*
9947 * Now we walk through the log, transaction by transaction,
9948 * making sure that each transaction has a commit block in the
9949 * expected place. Each complete transaction gets replayed back
9950 * into the main filesystem.
9951 */
9952
9953 while (1) {
9954 int flags;
9955 char * tagp;
9956 journal_block_tag_t * tag;
9957 struct buffer_head * obh;
9958 struct buffer_head * nbh;
9959
9960 /* If we already know where to stop the log traversal,
9961 * check right now that we haven't gone past the end of
9962 * the log. */
9963
9964 if (pass != PASS_SCAN)
9965 if (tid_geq(next_commit_ID, info->end_transaction))
9966 break;
9967
9968 /* Skip over each chunk of the transaction looking
9969 * either the next descriptor block or the final commit
9970 * record. */
9971
9972 err = jread(&bh, journal, next_log_block);
9973 if (err)
9974 goto failed;
9975
9976 next_log_block++;
9977 wrap(journal, next_log_block);
9978
9979 /* What kind of buffer is it?
9980 *
9981 * If it is a descriptor block, check that it has the
9982 * expected sequence number. Otherwise, we're all done
9983 * here. */
9984
9985 tmp = (journal_header_t *)bh->b_data;
9986
9987 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
9988 brelse(bh);
9989 break;
9990 }
9991
9992 blocktype = ntohl(tmp->h_blocktype);
9993 sequence = ntohl(tmp->h_sequence);
9994
9995 if (sequence != next_commit_ID) {
9996 brelse(bh);
9997 break;
9998 }
9999
10000 /* OK, we have a valid descriptor block which matches
10001 * all of the sequence number checks. What are we going
10002 * to do with it? That depends on the pass... */
10003
Denis Vlasenkobb045062008-09-27 14:06:06 +000010004 switch (blocktype) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010005 case JFS_DESCRIPTOR_BLOCK:
10006 /* If it is a valid descriptor block, replay it
10007 * in pass REPLAY; otherwise, just skip over the
10008 * blocks it describes. */
10009 if (pass != PASS_REPLAY) {
10010 next_log_block +=
10011 count_tags(bh, journal->j_blocksize);
10012 wrap(journal, next_log_block);
10013 brelse(bh);
10014 continue;
10015 }
10016
10017 /* A descriptor block: we can now write all of
10018 * the data blocks. Yay, useful work is finally
10019 * getting done here! */
10020
10021 tagp = &bh->b_data[sizeof(journal_header_t)];
10022 while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
10023 <= journal->j_blocksize) {
10024 unsigned long io_block;
10025
10026 tag = (journal_block_tag_t *) tagp;
10027 flags = ntohl(tag->t_flags);
10028
10029 io_block = next_log_block++;
10030 wrap(journal, next_log_block);
10031 err = jread(&obh, journal, io_block);
10032 if (err) {
10033 /* Recover what we can, but
10034 * report failure at the end. */
10035 success = err;
10036 printf("JBD: IO error %d recovering "
10037 "block %ld in log\n",
10038 err, io_block);
10039 } else {
10040 unsigned long blocknr;
10041
10042 blocknr = ntohl(tag->t_blocknr);
10043
10044 /* If the block has been
10045 * revoked, then we're all done
10046 * here. */
10047 if (journal_test_revoke
10048 (journal, blocknr,
10049 next_commit_ID)) {
10050 brelse(obh);
10051 ++info->nr_revoke_hits;
10052 goto skip_write;
10053 }
10054
10055 /* Find a buffer for the new
10056 * data being restored */
10057 nbh = getblk(journal->j_fs_dev,
10058 blocknr,
10059 journal->j_blocksize);
10060 if (nbh == NULL) {
10061 printf("JBD: Out of memory "
10062 "during recovery.\n");
10063 err = -ENOMEM;
10064 brelse(bh);
10065 brelse(obh);
10066 goto failed;
10067 }
10068
10069 lock_buffer(nbh);
10070 memcpy(nbh->b_data, obh->b_data,
10071 journal->j_blocksize);
10072 if (flags & JFS_FLAG_ESCAPE) {
10073 *((unsigned int *)bh->b_data) =
10074 htonl(JFS_MAGIC_NUMBER);
10075 }
10076
10077 mark_buffer_uptodate(nbh, 1);
10078 mark_buffer_dirty(nbh);
10079 ++info->nr_replays;
10080 /* ll_rw_block(WRITE, 1, &nbh); */
10081 unlock_buffer(nbh);
10082 brelse(obh);
10083 brelse(nbh);
10084 }
10085
10086 skip_write:
10087 tagp += sizeof(journal_block_tag_t);
10088 if (!(flags & JFS_FLAG_SAME_UUID))
10089 tagp += 16;
10090
10091 if (flags & JFS_FLAG_LAST_TAG)
10092 break;
10093 }
10094
10095 brelse(bh);
10096 continue;
10097
10098 case JFS_COMMIT_BLOCK:
10099 /* Found an expected commit block: not much to
10100 * do other than move on to the next sequence
10101 * number. */
10102 brelse(bh);
10103 next_commit_ID++;
10104 continue;
10105
10106 case JFS_REVOKE_BLOCK:
10107 /* If we aren't in the REVOKE pass, then we can
10108 * just skip over this block. */
10109 if (pass != PASS_REVOKE) {
10110 brelse(bh);
10111 continue;
10112 }
10113
10114 err = scan_revoke_records(journal, bh,
10115 next_commit_ID, info);
10116 brelse(bh);
10117 if (err)
10118 goto failed;
10119 continue;
10120
10121 default:
10122 goto done;
10123 }
10124 }
10125
10126 done:
10127 /*
10128 * We broke out of the log scan loop: either we came to the
10129 * known end of the log or we found an unexpected block in the
10130 * log. If the latter happened, then we know that the "current"
10131 * transaction marks the end of the valid log.
10132 */
10133
10134 if (pass == PASS_SCAN)
10135 info->end_transaction = next_commit_ID;
10136 else {
10137 /* It's really bad news if different passes end up at
10138 * different places (but possible due to IO errors). */
10139 if (info->end_transaction != next_commit_ID) {
10140 printf("JBD: recovery pass %d ended at "
10141 "transaction %u, expected %u\n",
10142 pass, next_commit_ID, info->end_transaction);
10143 if (!success)
10144 success = -EIO;
10145 }
10146 }
10147
10148 return success;
10149
10150 failed:
10151 return err;
10152}
10153
10154
10155/* Scan a revoke record, marking all blocks mentioned as revoked. */
10156
10157static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
10158 tid_t sequence, struct recovery_info *info)
10159{
10160 journal_revoke_header_t *header;
10161 int offset, max;
10162
10163 header = (journal_revoke_header_t *) bh->b_data;
10164 offset = sizeof(journal_revoke_header_t);
10165 max = ntohl(header->r_count);
10166
10167 while (offset < max) {
10168 unsigned long blocknr;
10169 int err;
10170
10171 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
10172 offset += 4;
10173 err = journal_set_revoke(journal, blocknr, sequence);
10174 if (err)
10175 return err;
10176 ++info->nr_revokes;
10177 }
10178 return 0;
10179}
10180
10181
10182/*
10183 * rehash.c --- rebuild hash tree directories
10184 *
10185 * This algorithm is designed for simplicity of implementation and to
10186 * pack the directory as much as possible. It however requires twice
10187 * as much memory as the size of the directory. The maximum size
10188 * directory supported using a 4k blocksize is roughly a gigabyte, and
10189 * so there may very well be problems with machines that don't have
10190 * virtual memory, and obscenely large directories.
10191 *
10192 * An alternate algorithm which is much more disk intensive could be
10193 * written, and probably will need to be written in the future. The
10194 * design goals of such an algorithm are: (a) use (roughly) constant
10195 * amounts of memory, no matter how large the directory, (b) the
10196 * directory must be safe at all times, even if e2fsck is interrupted
10197 * in the middle, (c) we must use minimal amounts of extra disk
10198 * blocks. This pretty much requires an incremental approach, where
10199 * we are reading from one part of the directory, and inserting into
10200 * the front half. So the algorithm will have to keep track of a
10201 * moving block boundary between the new tree and the old tree, and
10202 * files will need to be moved from the old directory and inserted
10203 * into the new tree. If the new directory requires space which isn't
10204 * yet available, blocks from the beginning part of the old directory
10205 * may need to be moved to the end of the directory to make room for
10206 * the new tree:
10207 *
10208 * --------------------------------------------------------
10209 * | new tree | | old tree |
10210 * --------------------------------------------------------
10211 * ^ ptr ^ptr
10212 * tail new head old
10213 *
10214 * This is going to be a pain in the tuckus to implement, and will
10215 * require a lot more disk accesses. So I'm going to skip it for now;
10216 * it's only really going to be an issue for really, really big
10217 * filesystems (when we reach the level of tens of millions of files
10218 * in a single directory). It will probably be easier to simply
10219 * require that e2fsck use VM first.
10220 */
10221
10222struct fill_dir_struct {
10223 char *buf;
10224 struct ext2_inode *inode;
10225 int err;
10226 e2fsck_t ctx;
10227 struct hash_entry *harray;
10228 int max_array, num_array;
10229 int dir_size;
10230 int compress;
10231 ino_t parent;
10232};
10233
10234struct hash_entry {
10235 ext2_dirhash_t hash;
10236 ext2_dirhash_t minor_hash;
10237 struct ext2_dir_entry *dir;
10238};
10239
10240struct out_dir {
10241 int num;
10242 int max;
10243 char *buf;
10244 ext2_dirhash_t *hashes;
10245};
10246
10247static int fill_dir_block(ext2_filsys fs,
10248 blk_t *block_nr,
10249 e2_blkcnt_t blockcnt,
10250 blk_t ref_block FSCK_ATTR((unused)),
10251 int ref_offset FSCK_ATTR((unused)),
10252 void *priv_data)
10253{
10254 struct fill_dir_struct *fd = (struct fill_dir_struct *) priv_data;
10255 struct hash_entry *new_array, *ent;
10256 struct ext2_dir_entry *dirent;
10257 char *dir;
10258 unsigned int offset, dir_offset;
10259
10260 if (blockcnt < 0)
10261 return 0;
10262
10263 offset = blockcnt * fs->blocksize;
10264 if (offset + fs->blocksize > fd->inode->i_size) {
10265 fd->err = EXT2_ET_DIR_CORRUPTED;
10266 return BLOCK_ABORT;
10267 }
10268 dir = (fd->buf+offset);
10269 if (HOLE_BLKADDR(*block_nr)) {
10270 memset(dir, 0, fs->blocksize);
10271 dirent = (struct ext2_dir_entry *) dir;
10272 dirent->rec_len = fs->blocksize;
10273 } else {
10274 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
10275 if (fd->err)
10276 return BLOCK_ABORT;
10277 }
10278 /* While the directory block is "hot", index it. */
10279 dir_offset = 0;
10280 while (dir_offset < fs->blocksize) {
10281 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
10282 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
10283 (dirent->rec_len < 8) ||
10284 ((dirent->rec_len % 4) != 0) ||
10285 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
10286 fd->err = EXT2_ET_DIR_CORRUPTED;
10287 return BLOCK_ABORT;
10288 }
10289 dir_offset += dirent->rec_len;
10290 if (dirent->inode == 0)
10291 continue;
10292 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
10293 (dirent->name[0] == '.'))
10294 continue;
10295 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
10296 (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
10297 fd->parent = dirent->inode;
10298 continue;
10299 }
10300 if (fd->num_array >= fd->max_array) {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010301 new_array = xrealloc(fd->harray,
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010302 sizeof(struct hash_entry) * (fd->max_array+500));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010303 fd->harray = new_array;
10304 fd->max_array += 500;
10305 }
10306 ent = fd->harray + fd->num_array++;
10307 ent->dir = dirent;
10308 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
10309 if (fd->compress)
10310 ent->hash = ent->minor_hash = 0;
10311 else {
10312 fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
10313 dirent->name,
10314 dirent->name_len & 0xFF,
10315 fs->super->s_hash_seed,
10316 &ent->hash, &ent->minor_hash);
10317 if (fd->err)
10318 return BLOCK_ABORT;
10319 }
10320 }
10321
10322 return 0;
10323}
10324
10325/* Used for sorting the hash entry */
10326static int name_cmp(const void *a, const void *b)
10327{
10328 const struct hash_entry *he_a = (const struct hash_entry *) a;
10329 const struct hash_entry *he_b = (const struct hash_entry *) b;
10330 int ret;
10331 int min_len;
10332
10333 min_len = he_a->dir->name_len;
10334 if (min_len > he_b->dir->name_len)
10335 min_len = he_b->dir->name_len;
10336
10337 ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
10338 if (ret == 0) {
10339 if (he_a->dir->name_len > he_b->dir->name_len)
10340 ret = 1;
10341 else if (he_a->dir->name_len < he_b->dir->name_len)
10342 ret = -1;
10343 else
10344 ret = he_b->dir->inode - he_a->dir->inode;
10345 }
10346 return ret;
10347}
10348
10349/* Used for sorting the hash entry */
10350static int hash_cmp(const void *a, const void *b)
10351{
10352 const struct hash_entry *he_a = (const struct hash_entry *) a;
10353 const struct hash_entry *he_b = (const struct hash_entry *) b;
10354 int ret;
10355
10356 if (he_a->hash > he_b->hash)
10357 ret = 1;
10358 else if (he_a->hash < he_b->hash)
10359 ret = -1;
10360 else {
10361 if (he_a->minor_hash > he_b->minor_hash)
10362 ret = 1;
10363 else if (he_a->minor_hash < he_b->minor_hash)
10364 ret = -1;
10365 else
10366 ret = name_cmp(a, b);
10367 }
10368 return ret;
10369}
10370
10371static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
10372 int blocks)
10373{
10374 void *new_mem;
10375
10376 if (outdir->max) {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010377 new_mem = xrealloc(outdir->buf, blocks * fs->blocksize);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010378 outdir->buf = new_mem;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010379 new_mem = xrealloc(outdir->hashes,
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010380 blocks * sizeof(ext2_dirhash_t));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010381 outdir->hashes = new_mem;
10382 } else {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010383 outdir->buf = xmalloc(blocks * fs->blocksize);
10384 outdir->hashes = xmalloc(blocks * sizeof(ext2_dirhash_t));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010385 outdir->num = 0;
10386 }
10387 outdir->max = blocks;
10388 return 0;
10389}
10390
10391static void free_out_dir(struct out_dir *outdir)
10392{
10393 free(outdir->buf);
10394 free(outdir->hashes);
10395 outdir->max = 0;
10396 outdir->num =0;
10397}
10398
10399static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
10400 char ** ret)
10401{
10402 errcode_t retval;
10403
10404 if (outdir->num >= outdir->max) {
10405 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
10406 if (retval)
10407 return retval;
10408 }
10409 *ret = outdir->buf + (outdir->num++ * fs->blocksize);
10410 memset(*ret, 0, fs->blocksize);
10411 return 0;
10412}
10413
10414/*
10415 * This function is used to make a unique filename. We do this by
10416 * appending ~0, and then incrementing the number. However, we cannot
10417 * expand the length of the filename beyond the padding available in
10418 * the directory entry.
10419 */
10420static void mutate_name(char *str, __u16 *len)
10421{
10422 int i;
10423 __u16 l = *len & 0xFF, h = *len & 0xff00;
10424
10425 /*
10426 * First check to see if it looks the name has been mutated
10427 * already
10428 */
10429 for (i = l-1; i > 0; i--) {
10430 if (!isdigit(str[i]))
10431 break;
10432 }
10433 if ((i == l-1) || (str[i] != '~')) {
10434 if (((l-1) & 3) < 2)
10435 l += 2;
10436 else
10437 l = (l+3) & ~3;
10438 str[l-2] = '~';
10439 str[l-1] = '0';
10440 *len = l | h;
10441 return;
10442 }
10443 for (i = l-1; i >= 0; i--) {
10444 if (isdigit(str[i])) {
10445 if (str[i] == '9')
10446 str[i] = '0';
10447 else {
10448 str[i]++;
10449 return;
10450 }
10451 continue;
10452 }
10453 if (i == 1) {
10454 if (str[0] == 'z')
10455 str[0] = 'A';
10456 else if (str[0] == 'Z') {
10457 str[0] = '~';
10458 str[1] = '0';
10459 } else
10460 str[0]++;
10461 } else if (i > 0) {
10462 str[i] = '1';
10463 str[i-1] = '~';
10464 } else {
10465 if (str[0] == '~')
10466 str[0] = 'a';
10467 else
10468 str[0]++;
10469 }
10470 break;
10471 }
10472}
10473
10474static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
10475 ext2_ino_t ino,
10476 struct fill_dir_struct *fd)
10477{
10478 struct problem_context pctx;
10479 struct hash_entry *ent, *prev;
10480 int i, j;
10481 int fixed = 0;
10482 char new_name[256];
10483 __u16 new_len;
10484
10485 clear_problem_context(&pctx);
10486 pctx.ino = ino;
10487
10488 for (i=1; i < fd->num_array; i++) {
10489 ent = fd->harray + i;
10490 prev = ent - 1;
10491 if (!ent->dir->inode ||
10492 ((ent->dir->name_len & 0xFF) !=
10493 (prev->dir->name_len & 0xFF)) ||
10494 (strncmp(ent->dir->name, prev->dir->name,
10495 ent->dir->name_len & 0xFF)))
10496 continue;
10497 pctx.dirent = ent->dir;
10498 if ((ent->dir->inode == prev->dir->inode) &&
10499 fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
10500 e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
10501 ent->dir->inode = 0;
10502 fixed++;
10503 continue;
10504 }
10505 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
10506 new_len = ent->dir->name_len;
10507 mutate_name(new_name, &new_len);
10508 for (j=0; j < fd->num_array; j++) {
10509 if ((i==j) ||
10510 ((ent->dir->name_len & 0xFF) !=
10511 (fd->harray[j].dir->name_len & 0xFF)) ||
10512 (strncmp(new_name, fd->harray[j].dir->name,
10513 new_len & 0xFF)))
10514 continue;
10515 mutate_name(new_name, &new_len);
10516
10517 j = -1;
10518 }
10519 new_name[new_len & 0xFF] = 0;
10520 pctx.str = new_name;
10521 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
10522 memcpy(ent->dir->name, new_name, new_len & 0xFF);
10523 ent->dir->name_len = new_len;
10524 ext2fs_dirhash(fs->super->s_def_hash_version,
10525 ent->dir->name,
10526 ent->dir->name_len & 0xFF,
10527 fs->super->s_hash_seed,
10528 &ent->hash, &ent->minor_hash);
10529 fixed++;
10530 }
10531 }
10532 return fixed;
10533}
10534
10535
10536static errcode_t copy_dir_entries(ext2_filsys fs,
10537 struct fill_dir_struct *fd,
10538 struct out_dir *outdir)
10539{
10540 errcode_t retval;
10541 char *block_start;
10542 struct hash_entry *ent;
10543 struct ext2_dir_entry *dirent;
10544 int i, rec_len, left;
10545 ext2_dirhash_t prev_hash;
10546 int offset;
10547
10548 outdir->max = 0;
10549 retval = alloc_size_dir(fs, outdir,
10550 (fd->dir_size / fs->blocksize) + 2);
10551 if (retval)
10552 return retval;
10553 outdir->num = fd->compress ? 0 : 1;
10554 offset = 0;
10555 outdir->hashes[0] = 0;
10556 prev_hash = 1;
10557 if ((retval = get_next_block(fs, outdir, &block_start)))
10558 return retval;
10559 dirent = (struct ext2_dir_entry *) block_start;
10560 left = fs->blocksize;
10561 for (i=0; i < fd->num_array; i++) {
10562 ent = fd->harray + i;
10563 if (ent->dir->inode == 0)
10564 continue;
10565 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
10566 if (rec_len > left) {
10567 if (left)
10568 dirent->rec_len += left;
10569 if ((retval = get_next_block(fs, outdir,
10570 &block_start)))
10571 return retval;
10572 offset = 0;
10573 }
10574 left = fs->blocksize - offset;
10575 dirent = (struct ext2_dir_entry *) (block_start + offset);
10576 if (offset == 0) {
10577 if (ent->hash == prev_hash)
10578 outdir->hashes[outdir->num-1] = ent->hash | 1;
10579 else
10580 outdir->hashes[outdir->num-1] = ent->hash;
10581 }
10582 dirent->inode = ent->dir->inode;
10583 dirent->name_len = ent->dir->name_len;
10584 dirent->rec_len = rec_len;
10585 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
10586 offset += rec_len;
10587 left -= rec_len;
10588 if (left < 12) {
10589 dirent->rec_len += left;
10590 offset += left;
10591 left = 0;
10592 }
10593 prev_hash = ent->hash;
10594 }
10595 if (left)
10596 dirent->rec_len += left;
10597
10598 return 0;
10599}
10600
10601
10602static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
10603 ext2_ino_t ino, ext2_ino_t parent)
10604{
10605 struct ext2_dir_entry *dir;
10606 struct ext2_dx_root_info *root;
10607 struct ext2_dx_countlimit *limits;
10608 int filetype = 0;
10609
10610 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
10611 filetype = EXT2_FT_DIR << 8;
10612
10613 memset(buf, 0, fs->blocksize);
10614 dir = (struct ext2_dir_entry *) buf;
10615 dir->inode = ino;
10616 dir->name[0] = '.';
10617 dir->name_len = 1 | filetype;
10618 dir->rec_len = 12;
10619 dir = (struct ext2_dir_entry *) (buf + 12);
10620 dir->inode = parent;
10621 dir->name[0] = '.';
10622 dir->name[1] = '.';
10623 dir->name_len = 2 | filetype;
10624 dir->rec_len = fs->blocksize - 12;
10625
10626 root = (struct ext2_dx_root_info *) (buf+24);
10627 root->reserved_zero = 0;
10628 root->hash_version = fs->super->s_def_hash_version;
10629 root->info_length = 8;
10630 root->indirect_levels = 0;
10631 root->unused_flags = 0;
10632
10633 limits = (struct ext2_dx_countlimit *) (buf+32);
10634 limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
10635 limits->count = 0;
10636
10637 return root;
10638}
10639
10640
10641static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
10642{
10643 struct ext2_dir_entry *dir;
10644 struct ext2_dx_countlimit *limits;
10645
10646 memset(buf, 0, fs->blocksize);
10647 dir = (struct ext2_dir_entry *) buf;
10648 dir->inode = 0;
10649 dir->rec_len = fs->blocksize;
10650
10651 limits = (struct ext2_dx_countlimit *) (buf+8);
10652 limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
10653 limits->count = 0;
10654
10655 return (struct ext2_dx_entry *) limits;
10656}
10657
10658/*
10659 * This function takes the leaf nodes which have been written in
10660 * outdir, and populates the root node and any necessary interior nodes.
10661 */
10662static errcode_t calculate_tree(ext2_filsys fs,
10663 struct out_dir *outdir,
10664 ext2_ino_t ino,
10665 ext2_ino_t parent)
10666{
10667 struct ext2_dx_root_info *root_info;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +010010668 struct ext2_dx_entry *root, *dx_ent = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010669 struct ext2_dx_countlimit *root_limit, *limit;
10670 errcode_t retval;
10671 char * block_start;
10672 int i, c1, c2, nblks;
10673 int limit_offset, root_offset;
10674
10675 root_info = set_root_node(fs, outdir->buf, ino, parent);
10676 root_offset = limit_offset = ((char *) root_info - outdir->buf) +
10677 root_info->info_length;
10678 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10679 c1 = root_limit->limit;
10680 nblks = outdir->num;
10681
10682 /* Write out the pointer blocks */
10683 if (nblks-1 <= c1) {
10684 /* Just write out the root block, and we're done */
10685 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
10686 for (i=1; i < nblks; i++) {
10687 root->block = ext2fs_cpu_to_le32(i);
10688 if (i != 1)
10689 root->hash =
10690 ext2fs_cpu_to_le32(outdir->hashes[i]);
10691 root++;
10692 c1--;
10693 }
10694 } else {
10695 c2 = 0;
10696 limit = 0;
10697 root_info->indirect_levels = 1;
10698 for (i=1; i < nblks; i++) {
10699 if (c1 == 0)
10700 return ENOSPC;
10701 if (c2 == 0) {
10702 if (limit)
10703 limit->limit = limit->count =
10704 ext2fs_cpu_to_le16(limit->limit);
10705 root = (struct ext2_dx_entry *)
10706 (outdir->buf + root_offset);
10707 root->block = ext2fs_cpu_to_le32(outdir->num);
10708 if (i != 1)
10709 root->hash =
10710 ext2fs_cpu_to_le32(outdir->hashes[i]);
10711 if ((retval = get_next_block(fs, outdir,
10712 &block_start)))
10713 return retval;
10714 dx_ent = set_int_node(fs, block_start);
10715 limit = (struct ext2_dx_countlimit *) dx_ent;
10716 c2 = limit->limit;
10717 root_offset += sizeof(struct ext2_dx_entry);
10718 c1--;
10719 }
10720 dx_ent->block = ext2fs_cpu_to_le32(i);
10721 if (c2 != limit->limit)
10722 dx_ent->hash =
10723 ext2fs_cpu_to_le32(outdir->hashes[i]);
10724 dx_ent++;
10725 c2--;
10726 }
10727 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
10728 limit->limit = ext2fs_cpu_to_le16(limit->limit);
10729 }
10730 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10731 root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
10732 root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
10733
10734 return 0;
10735}
10736
10737struct write_dir_struct {
10738 struct out_dir *outdir;
10739 errcode_t err;
10740 e2fsck_t ctx;
10741 int cleared;
10742};
10743
10744/*
10745 * Helper function which writes out a directory block.
10746 */
10747static int write_dir_block(ext2_filsys fs,
10748 blk_t *block_nr,
10749 e2_blkcnt_t blockcnt,
10750 blk_t ref_block FSCK_ATTR((unused)),
10751 int ref_offset FSCK_ATTR((unused)),
10752 void *priv_data)
10753{
10754 struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
10755 blk_t blk;
10756 char *dir;
10757
10758 if (*block_nr == 0)
10759 return 0;
10760 if (blockcnt >= wd->outdir->num) {
10761 e2fsck_read_bitmaps(wd->ctx);
10762 blk = *block_nr;
10763 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
10764 ext2fs_block_alloc_stats(fs, blk, -1);
10765 *block_nr = 0;
10766 wd->cleared++;
10767 return BLOCK_CHANGED;
10768 }
10769 if (blockcnt < 0)
10770 return 0;
10771
10772 dir = wd->outdir->buf + (blockcnt * fs->blocksize);
10773 wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
10774 if (wd->err)
10775 return BLOCK_ABORT;
10776 return 0;
10777}
10778
10779static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
10780 struct out_dir *outdir,
10781 ext2_ino_t ino, int compress)
10782{
10783 struct write_dir_struct wd;
10784 errcode_t retval;
10785 struct ext2_inode inode;
10786
10787 retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
10788 if (retval)
10789 return retval;
10790
10791 wd.outdir = outdir;
10792 wd.err = 0;
10793 wd.ctx = ctx;
10794 wd.cleared = 0;
10795
10796 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10797 write_dir_block, &wd);
10798 if (retval)
10799 return retval;
10800 if (wd.err)
10801 return wd.err;
10802
10803 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10804 if (compress)
10805 inode.i_flags &= ~EXT2_INDEX_FL;
10806 else
10807 inode.i_flags |= EXT2_INDEX_FL;
10808 inode.i_size = outdir->num * fs->blocksize;
10809 inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
10810 e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
10811
10812 return 0;
10813}
10814
10815static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
10816{
10817 ext2_filsys fs = ctx->fs;
10818 errcode_t retval;
10819 struct ext2_inode inode;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +010010820 char *dir_buf = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010821 struct fill_dir_struct fd;
10822 struct out_dir outdir;
10823
10824 outdir.max = outdir.num = 0;
10825 outdir.buf = 0;
10826 outdir.hashes = 0;
10827 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10828
10829 retval = ENOMEM;
10830 fd.harray = 0;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010831 dir_buf = xmalloc(inode.i_size);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010832
10833 fd.max_array = inode.i_size / 32;
10834 fd.num_array = 0;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010835 fd.harray = xmalloc(fd.max_array * sizeof(struct hash_entry));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010836
10837 fd.ctx = ctx;
10838 fd.buf = dir_buf;
10839 fd.inode = &inode;
10840 fd.err = 0;
10841 fd.dir_size = 0;
10842 fd.compress = 0;
10843 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
10844 (inode.i_size / fs->blocksize) < 2)
10845 fd.compress = 1;
10846 fd.parent = 0;
10847
10848 /* Read in the entire directory into memory */
10849 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10850 fill_dir_block, &fd);
10851 if (fd.err) {
10852 retval = fd.err;
10853 goto errout;
10854 }
10855
10856 /* Sort the list */
10857resort:
10858 if (fd.compress)
10859 qsort(fd.harray+2, fd.num_array-2,
10860 sizeof(struct hash_entry), name_cmp);
10861 else
10862 qsort(fd.harray, fd.num_array,
10863 sizeof(struct hash_entry), hash_cmp);
10864
10865 /*
10866 * Look for duplicates
10867 */
10868 if (duplicate_search_and_fix(ctx, fs, ino, &fd))
10869 goto resort;
10870
10871 if (ctx->options & E2F_OPT_NO) {
10872 retval = 0;
10873 goto errout;
10874 }
10875
10876 /*
10877 * Copy the directory entries. In a htree directory these
10878 * will become the leaf nodes.
10879 */
10880 retval = copy_dir_entries(fs, &fd, &outdir);
10881 if (retval)
10882 goto errout;
10883
10884 free(dir_buf); dir_buf = 0;
10885
10886 if (!fd.compress) {
10887 /* Calculate the interior nodes */
10888 retval = calculate_tree(fs, &outdir, ino, fd.parent);
10889 if (retval)
10890 goto errout;
10891 }
10892
10893 retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
10894
10895errout:
10896 free(dir_buf);
10897 free(fd.harray);
10898
10899 free_out_dir(&outdir);
10900 return retval;
10901}
10902
10903void e2fsck_rehash_directories(e2fsck_t ctx)
10904{
10905 struct problem_context pctx;
10906 struct dir_info *dir;
10907 ext2_u32_iterate iter;
10908 ext2_ino_t ino;
10909 errcode_t retval;
10910 int i, cur, max, all_dirs, dir_index, first = 1;
10911
10912 all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
10913
10914 if (!ctx->dirs_to_hash && !all_dirs)
10915 return;
10916
10917 e2fsck_get_lost_and_found(ctx, 0);
10918
10919 clear_problem_context(&pctx);
10920
10921 dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
10922 cur = 0;
10923 if (all_dirs) {
10924 i = 0;
10925 max = e2fsck_get_num_dirinfo(ctx);
10926 } else {
10927 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
10928 &iter);
10929 if (retval) {
10930 pctx.errcode = retval;
10931 fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
10932 return;
10933 }
10934 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
10935 }
10936 while (1) {
10937 if (all_dirs) {
10938 if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
10939 break;
10940 ino = dir->ino;
10941 } else {
10942 if (!ext2fs_u32_list_iterate(iter, &ino))
10943 break;
10944 }
10945 if (ino == ctx->lost_and_found)
10946 continue;
10947 pctx.dir = ino;
10948 if (first) {
10949 fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
10950 first = 0;
10951 }
10952 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
10953 if (pctx.errcode) {
10954 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10955 fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
10956 }
10957 if (ctx->progress && !ctx->progress_fd)
10958 e2fsck_simple_progress(ctx, "Rebuilding directory",
10959 100.0 * (float) (++cur) / (float) max, ino);
10960 }
10961 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10962 if (!all_dirs)
10963 ext2fs_u32_list_iterate_end(iter);
10964
10965 ext2fs_u32_list_free(ctx->dirs_to_hash);
10966 ctx->dirs_to_hash = 0;
10967}
10968
10969/*
10970 * linux/fs/revoke.c
10971 *
10972 * Journal revoke routines for the generic filesystem journaling code;
10973 * part of the ext2fs journaling system.
10974 *
10975 * Revoke is the mechanism used to prevent old log records for deleted
10976 * metadata from being replayed on top of newer data using the same
10977 * blocks. The revoke mechanism is used in two separate places:
10978 *
10979 * + Commit: during commit we write the entire list of the current
10980 * transaction's revoked blocks to the journal
10981 *
10982 * + Recovery: during recovery we record the transaction ID of all
10983 * revoked blocks. If there are multiple revoke records in the log
10984 * for a single block, only the last one counts, and if there is a log
10985 * entry for a block beyond the last revoke, then that log entry still
10986 * gets replayed.
10987 *
10988 * We can get interactions between revokes and new log data within a
10989 * single transaction:
10990 *
10991 * Block is revoked and then journaled:
10992 * The desired end result is the journaling of the new block, so we
10993 * cancel the revoke before the transaction commits.
10994 *
10995 * Block is journaled and then revoked:
10996 * The revoke must take precedence over the write of the block, so we
10997 * need either to cancel the journal entry or to write the revoke
10998 * later in the log than the log block. In this case, we choose the
10999 * latter: journaling a block cancels any revoke record for that block
11000 * in the current transaction, so any revoke for that block in the
11001 * transaction must have happened after the block was journaled and so
11002 * the revoke must take precedence.
11003 *
11004 * Block is revoked and then written as data:
11005 * The data write is allowed to succeed, but the revoke is _not_
11006 * cancelled. We still need to prevent old log records from
11007 * overwriting the new data. We don't even need to clear the revoke
11008 * bit here.
11009 *
11010 * Revoke information on buffers is a tri-state value:
11011 *
11012 * RevokeValid clear: no cached revoke status, need to look it up
11013 * RevokeValid set, Revoked clear:
11014 * buffer has not been revoked, and cancel_revoke
11015 * need do nothing.
11016 * RevokeValid set, Revoked set:
11017 * buffer has been revoked.
11018 */
11019
11020static kmem_cache_t *revoke_record_cache;
11021static kmem_cache_t *revoke_table_cache;
11022
11023/* Each revoke record represents one single revoked block. During
11024 journal replay, this involves recording the transaction ID of the
11025 last transaction to revoke this block. */
11026
11027struct jbd_revoke_record_s
11028{
11029 struct list_head hash;
11030 tid_t sequence; /* Used for recovery only */
11031 unsigned long blocknr;
11032};
11033
11034
11035/* The revoke table is just a simple hash table of revoke records. */
11036struct jbd_revoke_table_s
11037{
11038 /* It is conceivable that we might want a larger hash table
11039 * for recovery. Must be a power of two. */
11040 int hash_size;
11041 int hash_shift;
11042 struct list_head *hash_table;
11043};
11044
11045
11046/* Utility functions to maintain the revoke table */
11047
11048/* Borrowed from buffer.c: this is a tried and tested block hash function */
11049static int hash(journal_t *journal, unsigned long block)
11050{
11051 struct jbd_revoke_table_s *table = journal->j_revoke;
11052 int hash_shift = table->hash_shift;
11053
11054 return ((block << (hash_shift - 6)) ^
11055 (block >> 13) ^
11056 (block << (hash_shift - 12))) & (table->hash_size - 1);
11057}
11058
11059static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
11060 tid_t seq)
11061{
11062 struct list_head *hash_list;
11063 struct jbd_revoke_record_s *record;
11064
11065 record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
11066 if (!record)
11067 goto oom;
11068
11069 record->sequence = seq;
11070 record->blocknr = blocknr;
11071 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11072 list_add(&record->hash, hash_list);
11073 return 0;
11074
11075oom:
11076 return -ENOMEM;
11077}
11078
11079/* Find a revoke record in the journal's hash table. */
11080
11081static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
11082 unsigned long blocknr)
11083{
11084 struct list_head *hash_list;
11085 struct jbd_revoke_record_s *record;
11086
11087 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11088
11089 record = (struct jbd_revoke_record_s *) hash_list->next;
11090 while (&(record->hash) != hash_list) {
11091 if (record->blocknr == blocknr)
11092 return record;
11093 record = (struct jbd_revoke_record_s *) record->hash.next;
11094 }
11095 return NULL;
11096}
11097
11098int journal_init_revoke_caches(void)
11099{
11100 revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
11101 if (revoke_record_cache == 0)
11102 return -ENOMEM;
11103
11104 revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
11105 if (revoke_table_cache == 0) {
11106 do_cache_destroy(revoke_record_cache);
11107 revoke_record_cache = NULL;
11108 return -ENOMEM;
11109 }
11110 return 0;
11111}
11112
11113void journal_destroy_revoke_caches(void)
11114{
11115 do_cache_destroy(revoke_record_cache);
11116 revoke_record_cache = 0;
11117 do_cache_destroy(revoke_table_cache);
11118 revoke_table_cache = 0;
11119}
11120
11121/* Initialise the revoke table for a given journal to a given size. */
11122
11123int journal_init_revoke(journal_t *journal, int hash_size)
11124{
11125 int shift, tmp;
11126
11127 journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
11128 if (!journal->j_revoke)
11129 return -ENOMEM;
11130
11131 /* Check that the hash_size is a power of two */
11132 journal->j_revoke->hash_size = hash_size;
11133
11134 shift = 0;
11135 tmp = hash_size;
Denis Vlasenkobb045062008-09-27 14:06:06 +000011136 while ((tmp >>= 1UL) != 0UL)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011137 shift++;
11138 journal->j_revoke->hash_shift = shift;
11139
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010011140 journal->j_revoke->hash_table = xmalloc(hash_size * sizeof(struct list_head));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011141
11142 for (tmp = 0; tmp < hash_size; tmp++)
11143 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
11144
11145 return 0;
11146}
11147
11148/* Destoy a journal's revoke table. The table must already be empty! */
11149
11150void journal_destroy_revoke(journal_t *journal)
11151{
11152 struct jbd_revoke_table_s *table;
11153 struct list_head *hash_list;
11154 int i;
11155
11156 table = journal->j_revoke;
11157 if (!table)
11158 return;
11159
11160 for (i=0; i<table->hash_size; i++) {
11161 hash_list = &table->hash_table[i];
11162 }
11163
11164 free(table->hash_table);
11165 free(table);
11166 journal->j_revoke = NULL;
11167}
11168
11169/*
11170 * Revoke support for recovery.
11171 *
11172 * Recovery needs to be able to:
11173 *
11174 * record all revoke records, including the tid of the latest instance
11175 * of each revoke in the journal
11176 *
11177 * check whether a given block in a given transaction should be replayed
11178 * (ie. has not been revoked by a revoke record in that or a subsequent
11179 * transaction)
11180 *
11181 * empty the revoke table after recovery.
11182 */
11183
11184/*
11185 * First, setting revoke records. We create a new revoke record for
11186 * every block ever revoked in the log as we scan it for recovery, and
11187 * we update the existing records if we find multiple revokes for a
11188 * single block.
11189 */
11190
11191int journal_set_revoke(journal_t *journal, unsigned long blocknr,
11192 tid_t sequence)
11193{
11194 struct jbd_revoke_record_s *record;
11195
11196 record = find_revoke_record(journal, blocknr);
11197 if (record) {
11198 /* If we have multiple occurences, only record the
11199 * latest sequence number in the hashed record */
11200 if (tid_gt(sequence, record->sequence))
11201 record->sequence = sequence;
11202 return 0;
11203 }
11204 return insert_revoke_hash(journal, blocknr, sequence);
11205}
11206
11207/*
11208 * Test revoke records. For a given block referenced in the log, has
11209 * that block been revoked? A revoke record with a given transaction
11210 * sequence number revokes all blocks in that transaction and earlier
11211 * ones, but later transactions still need replayed.
11212 */
11213
11214int journal_test_revoke(journal_t *journal, unsigned long blocknr,
11215 tid_t sequence)
11216{
11217 struct jbd_revoke_record_s *record;
11218
11219 record = find_revoke_record(journal, blocknr);
11220 if (!record)
11221 return 0;
11222 if (tid_gt(sequence, record->sequence))
11223 return 0;
11224 return 1;
11225}
11226
11227/*
11228 * Finally, once recovery is over, we need to clear the revoke table so
11229 * that it can be reused by the running filesystem.
11230 */
11231
11232void journal_clear_revoke(journal_t *journal)
11233{
11234 int i;
11235 struct list_head *hash_list;
11236 struct jbd_revoke_record_s *record;
11237 struct jbd_revoke_table_s *revoke_var;
11238
11239 revoke_var = journal->j_revoke;
11240
11241 for (i = 0; i < revoke_var->hash_size; i++) {
11242 hash_list = &revoke_var->hash_table[i];
11243 while (!list_empty(hash_list)) {
11244 record = (struct jbd_revoke_record_s*) hash_list->next;
11245 list_del(&record->hash);
11246 free(record);
11247 }
11248 }
11249}
11250
11251/*
11252 * e2fsck.c - superblock checks
11253 */
11254
11255#define MIN_CHECK 1
11256#define MAX_CHECK 2
11257
11258static void check_super_value(e2fsck_t ctx, const char *descr,
11259 unsigned long value, int flags,
11260 unsigned long min_val, unsigned long max_val)
11261{
11262 struct problem_context pctx;
11263
11264 if (((flags & MIN_CHECK) && (value < min_val)) ||
11265 ((flags & MAX_CHECK) && (value > max_val))) {
11266 clear_problem_context(&pctx);
11267 pctx.num = value;
11268 pctx.str = descr;
11269 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11270 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11271 }
11272}
11273
11274/*
11275 * This routine may get stubbed out in special compilations of the
11276 * e2fsck code..
11277 */
11278#ifndef EXT2_SPECIAL_DEVICE_SIZE
11279static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
11280{
11281 return (ext2fs_get_device_size(ctx->filesystem_name,
11282 EXT2_BLOCK_SIZE(ctx->fs->super),
11283 &ctx->num_blocks));
11284}
11285#endif
11286
11287/*
11288 * helper function to release an inode
11289 */
11290struct process_block_struct {
11291 e2fsck_t ctx;
11292 char *buf;
11293 struct problem_context *pctx;
11294 int truncating;
11295 int truncate_offset;
11296 e2_blkcnt_t truncate_block;
11297 int truncated_blocks;
11298 int abort;
11299 errcode_t errcode;
11300};
11301
11302static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
11303 e2_blkcnt_t blockcnt,
11304 blk_t ref_blk FSCK_ATTR((unused)),
11305 int ref_offset FSCK_ATTR((unused)),
11306 void *priv_data)
11307{
11308 struct process_block_struct *pb;
11309 e2fsck_t ctx;
11310 struct problem_context *pctx;
11311 blk_t blk = *block_nr;
11312 int retval = 0;
11313
11314 pb = (struct process_block_struct *) priv_data;
11315 ctx = pb->ctx;
11316 pctx = pb->pctx;
11317
11318 pctx->blk = blk;
11319 pctx->blkcount = blockcnt;
11320
11321 if (HOLE_BLKADDR(blk))
11322 return 0;
11323
11324 if ((blk < fs->super->s_first_data_block) ||
11325 (blk >= fs->super->s_blocks_count)) {
11326 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
11327 return_abort:
11328 pb->abort = 1;
11329 return BLOCK_ABORT;
11330 }
11331
11332 if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
11333 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
11334 goto return_abort;
11335 }
11336
11337 /*
11338 * If we are deleting an orphan, then we leave the fields alone.
11339 * If we are truncating an orphan, then update the inode fields
11340 * and clean up any partial block data.
11341 */
11342 if (pb->truncating) {
11343 /*
11344 * We only remove indirect blocks if they are
11345 * completely empty.
11346 */
11347 if (blockcnt < 0) {
11348 int i, limit;
11349 blk_t *bp;
11350
11351 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11352 pb->buf);
11353 if (pb->errcode)
11354 goto return_abort;
11355
11356 limit = fs->blocksize >> 2;
11357 for (i = 0, bp = (blk_t *) pb->buf;
11358 i < limit; i++, bp++)
11359 if (*bp)
11360 return 0;
11361 }
11362 /*
11363 * We don't remove direct blocks until we've reached
11364 * the truncation block.
11365 */
11366 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
11367 return 0;
11368 /*
11369 * If part of the last block needs truncating, we do
11370 * it here.
11371 */
11372 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
11373 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11374 pb->buf);
11375 if (pb->errcode)
11376 goto return_abort;
11377 memset(pb->buf + pb->truncate_offset, 0,
11378 fs->blocksize - pb->truncate_offset);
11379 pb->errcode = io_channel_write_blk(fs->io, blk, 1,
11380 pb->buf);
11381 if (pb->errcode)
11382 goto return_abort;
11383 }
11384 pb->truncated_blocks++;
11385 *block_nr = 0;
11386 retval |= BLOCK_CHANGED;
11387 }
11388
11389 ext2fs_block_alloc_stats(fs, blk, -1);
11390 return retval;
11391}
11392
11393/*
11394 * This function releases an inode. Returns 1 if an inconsistency was
11395 * found. If the inode has a link count, then it is being truncated and
11396 * not deleted.
11397 */
11398static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
11399 struct ext2_inode *inode, char *block_buf,
11400 struct problem_context *pctx)
11401{
11402 struct process_block_struct pb;
11403 ext2_filsys fs = ctx->fs;
11404 errcode_t retval;
11405 __u32 count;
11406
11407 if (!ext2fs_inode_has_valid_blocks(inode))
11408 return 0;
11409
11410 pb.buf = block_buf + 3 * ctx->fs->blocksize;
11411 pb.ctx = ctx;
11412 pb.abort = 0;
11413 pb.errcode = 0;
11414 pb.pctx = pctx;
11415 if (inode->i_links_count) {
11416 pb.truncating = 1;
11417 pb.truncate_block = (e2_blkcnt_t)
11418 ((((long long)inode->i_size_high << 32) +
11419 inode->i_size + fs->blocksize - 1) /
11420 fs->blocksize);
11421 pb.truncate_offset = inode->i_size % fs->blocksize;
11422 } else {
11423 pb.truncating = 0;
11424 pb.truncate_block = 0;
11425 pb.truncate_offset = 0;
11426 }
11427 pb.truncated_blocks = 0;
11428 retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
11429 block_buf, release_inode_block, &pb);
11430 if (retval) {
11431 bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
11432 ino);
11433 return 1;
11434 }
11435 if (pb.abort)
11436 return 1;
11437
11438 /* Refresh the inode since ext2fs_block_iterate may have changed it */
11439 e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
11440
11441 if (pb.truncated_blocks)
11442 inode->i_blocks -= pb.truncated_blocks *
11443 (fs->blocksize / 512);
11444
11445 if (inode->i_file_acl) {
11446 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
11447 block_buf, -1, &count);
11448 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
11449 retval = 0;
11450 count = 1;
11451 }
11452 if (retval) {
11453 bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
11454 ino);
11455 return 1;
11456 }
11457 if (count == 0)
11458 ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
11459 inode->i_file_acl = 0;
11460 }
11461 return 0;
11462}
11463
11464/*
11465 * This function releases all of the orphan inodes. It returns 1 if
11466 * it hit some error, and 0 on success.
11467 */
11468static int release_orphan_inodes(e2fsck_t ctx)
11469{
11470 ext2_filsys fs = ctx->fs;
11471 ext2_ino_t ino, next_ino;
11472 struct ext2_inode inode;
11473 struct problem_context pctx;
11474 char *block_buf;
11475
11476 if ((ino = fs->super->s_last_orphan) == 0)
11477 return 0;
11478
11479 /*
11480 * Win or lose, we won't be using the head of the orphan inode
11481 * list again.
11482 */
11483 fs->super->s_last_orphan = 0;
11484 ext2fs_mark_super_dirty(fs);
11485
11486 /*
11487 * If the filesystem contains errors, don't run the orphan
11488 * list, since the orphan list can't be trusted; and we're
11489 * going to be running a full e2fsck run anyway...
11490 */
11491 if (fs->super->s_state & EXT2_ERROR_FS)
11492 return 0;
11493
11494 if ((ino < EXT2_FIRST_INODE(fs->super)) ||
11495 (ino > fs->super->s_inodes_count)) {
11496 clear_problem_context(&pctx);
11497 pctx.ino = ino;
11498 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
11499 return 1;
11500 }
11501
11502 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
11503 "block iterate buffer");
11504 e2fsck_read_bitmaps(ctx);
11505
11506 while (ino) {
11507 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
11508 clear_problem_context(&pctx);
11509 pctx.ino = ino;
11510 pctx.inode = &inode;
11511 pctx.str = inode.i_links_count ? _("Truncating") :
11512 _("Clearing");
11513
11514 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
11515
11516 next_ino = inode.i_dtime;
11517 if (next_ino &&
11518 ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
11519 (next_ino > fs->super->s_inodes_count))) {
11520 pctx.ino = next_ino;
11521 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
11522 goto return_abort;
11523 }
11524
11525 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
11526 goto return_abort;
11527
11528 if (!inode.i_links_count) {
11529 ext2fs_inode_alloc_stats2(fs, ino, -1,
11530 LINUX_S_ISDIR(inode.i_mode));
Denis Vlasenko04158e02009-02-02 10:48:06 +000011531 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011532 } else {
11533 inode.i_dtime = 0;
11534 }
11535 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
11536 ino = next_ino;
11537 }
11538 ext2fs_free_mem(&block_buf);
11539 return 0;
11540return_abort:
11541 ext2fs_free_mem(&block_buf);
11542 return 1;
11543}
11544
11545/*
11546 * Check the resize inode to make sure it is sane. We check both for
11547 * the case where on-line resizing is not enabled (in which case the
11548 * resize inode should be cleared) as well as the case where on-line
11549 * resizing is enabled.
11550 */
11551static void check_resize_inode(e2fsck_t ctx)
11552{
11553 ext2_filsys fs = ctx->fs;
11554 struct ext2_inode inode;
11555 struct problem_context pctx;
11556 int i, j, gdt_off, ind_off;
11557 blk_t blk, pblk, expect;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +010011558 __u32 *dind_buf = NULL, *ind_buf;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011559 errcode_t retval;
11560
11561 clear_problem_context(&pctx);
11562
11563 /*
11564 * If the resize inode feature isn't set, then
11565 * s_reserved_gdt_blocks must be zero.
11566 */
11567 if (!(fs->super->s_feature_compat &
11568 EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11569 if (fs->super->s_reserved_gdt_blocks) {
11570 pctx.num = fs->super->s_reserved_gdt_blocks;
11571 if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
11572 &pctx)) {
11573 fs->super->s_reserved_gdt_blocks = 0;
11574 ext2fs_mark_super_dirty(fs);
11575 }
11576 }
11577 }
11578
11579 /* Read the resize inode */
11580 pctx.ino = EXT2_RESIZE_INO;
11581 retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
11582 if (retval) {
11583 if (fs->super->s_feature_compat &
11584 EXT2_FEATURE_COMPAT_RESIZE_INODE)
11585 ctx->flags |= E2F_FLAG_RESIZE_INODE;
11586 return;
11587 }
11588
11589 /*
11590 * If the resize inode feature isn't set, check to make sure
11591 * the resize inode is cleared; then we're done.
11592 */
11593 if (!(fs->super->s_feature_compat &
11594 EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11595 for (i=0; i < EXT2_N_BLOCKS; i++) {
11596 if (inode.i_block[i])
11597 break;
11598 }
11599 if ((i < EXT2_N_BLOCKS) &&
11600 fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
11601 memset(&inode, 0, sizeof(inode));
11602 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11603 "clear_resize");
11604 }
11605 return;
11606 }
11607
11608 /*
11609 * The resize inode feature is enabled; check to make sure the
11610 * only block in use is the double indirect block
11611 */
11612 blk = inode.i_block[EXT2_DIND_BLOCK];
11613 for (i=0; i < EXT2_N_BLOCKS; i++) {
11614 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
11615 break;
11616 }
11617 if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
11618 !(inode.i_mode & LINUX_S_IFREG) ||
11619 (blk < fs->super->s_first_data_block ||
11620 blk >= fs->super->s_blocks_count)) {
11621 resize_inode_invalid:
11622 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
11623 memset(&inode, 0, sizeof(inode));
11624 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11625 "clear_resize");
11626 ctx->flags |= E2F_FLAG_RESIZE_INODE;
11627 }
11628 if (!(ctx->options & E2F_OPT_READONLY)) {
11629 fs->super->s_state &= ~EXT2_VALID_FS;
11630 ext2fs_mark_super_dirty(fs);
11631 }
11632 goto cleanup;
11633 }
11634 dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
11635 "resize dind buffer");
11636 ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
11637
11638 retval = ext2fs_read_ind_block(fs, blk, dind_buf);
11639 if (retval)
11640 goto resize_inode_invalid;
11641
11642 gdt_off = fs->desc_blocks;
11643 pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
11644 for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
11645 i++, gdt_off++, pblk++) {
11646 gdt_off %= fs->blocksize/4;
11647 if (dind_buf[gdt_off] != pblk)
11648 goto resize_inode_invalid;
11649 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
11650 if (retval)
11651 goto resize_inode_invalid;
11652 ind_off = 0;
11653 for (j = 1; j < fs->group_desc_count; j++) {
11654 if (!ext2fs_bg_has_super(fs, j))
11655 continue;
11656 expect = pblk + (j * fs->super->s_blocks_per_group);
11657 if (ind_buf[ind_off] != expect)
11658 goto resize_inode_invalid;
11659 ind_off++;
11660 }
11661 }
11662
11663cleanup:
11664 ext2fs_free_mem(&dind_buf);
11665
11666 }
11667
11668static void check_super_block(e2fsck_t ctx)
11669{
11670 ext2_filsys fs = ctx->fs;
11671 blk_t first_block, last_block;
11672 struct ext2_super_block *sb = fs->super;
11673 struct ext2_group_desc *gd;
11674 blk_t blocks_per_group = fs->super->s_blocks_per_group;
11675 blk_t bpg_max;
11676 int inodes_per_block;
11677 int ipg_max;
11678 int inode_size;
11679 dgrp_t i;
11680 blk_t should_be;
11681 struct problem_context pctx;
11682 __u32 free_blocks = 0, free_inodes = 0;
11683
11684 inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
11685 ipg_max = inodes_per_block * (blocks_per_group - 4);
11686 if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
11687 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
11688 bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
11689 if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
11690 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
11691
11692 ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11693 sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
11694 ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11695 sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
11696 ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
11697 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
11698
11699 clear_problem_context(&pctx);
11700
11701 /*
11702 * Verify the super block constants...
11703 */
11704 check_super_value(ctx, "inodes_count", sb->s_inodes_count,
11705 MIN_CHECK, 1, 0);
11706 check_super_value(ctx, "blocks_count", sb->s_blocks_count,
11707 MIN_CHECK, 1, 0);
11708 check_super_value(ctx, "first_data_block", sb->s_first_data_block,
11709 MAX_CHECK, 0, sb->s_blocks_count);
11710 check_super_value(ctx, "log_block_size", sb->s_log_block_size,
11711 MIN_CHECK | MAX_CHECK, 0,
11712 EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
11713 check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
11714 MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
11715 check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
11716 MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
11717 bpg_max);
11718 check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
11719 MIN_CHECK | MAX_CHECK, 8, bpg_max);
11720 check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
11721 MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
11722 check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
11723 MAX_CHECK, 0, sb->s_blocks_count / 2);
11724 check_super_value(ctx, "reserved_gdt_blocks",
11725 sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
11726 fs->blocksize/4);
11727 inode_size = EXT2_INODE_SIZE(sb);
11728 check_super_value(ctx, "inode_size",
11729 inode_size, MIN_CHECK | MAX_CHECK,
11730 EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
11731 if (inode_size & (inode_size - 1)) {
11732 pctx.num = inode_size;
11733 pctx.str = "inode_size";
11734 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11735 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11736 return;
11737 }
11738
11739 if (!ctx->num_blocks) {
11740 pctx.errcode = e2fsck_get_device_size(ctx);
11741 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
11742 fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
11743 ctx->flags |= E2F_FLAG_ABORT;
11744 return;
11745 }
11746 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
11747 (ctx->num_blocks < sb->s_blocks_count)) {
11748 pctx.blk = sb->s_blocks_count;
11749 pctx.blk2 = ctx->num_blocks;
11750 if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
11751 ctx->flags |= E2F_FLAG_ABORT;
11752 return;
11753 }
11754 }
11755 }
11756
11757 if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
11758 pctx.blk = EXT2_BLOCK_SIZE(sb);
11759 pctx.blk2 = EXT2_FRAG_SIZE(sb);
11760 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
11761 ctx->flags |= E2F_FLAG_ABORT;
11762 return;
11763 }
11764
11765 should_be = sb->s_frags_per_group >>
11766 (sb->s_log_block_size - sb->s_log_frag_size);
11767 if (sb->s_blocks_per_group != should_be) {
11768 pctx.blk = sb->s_blocks_per_group;
11769 pctx.blk2 = should_be;
11770 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
11771 ctx->flags |= E2F_FLAG_ABORT;
11772 return;
11773 }
11774
11775 should_be = (sb->s_log_block_size == 0) ? 1 : 0;
11776 if (sb->s_first_data_block != should_be) {
11777 pctx.blk = sb->s_first_data_block;
11778 pctx.blk2 = should_be;
11779 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
11780 ctx->flags |= E2F_FLAG_ABORT;
11781 return;
11782 }
11783
11784 should_be = sb->s_inodes_per_group * fs->group_desc_count;
11785 if (sb->s_inodes_count != should_be) {
11786 pctx.ino = sb->s_inodes_count;
11787 pctx.ino2 = should_be;
11788 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
11789 sb->s_inodes_count = should_be;
11790 ext2fs_mark_super_dirty(fs);
11791 }
11792 }
11793
11794 /*
11795 * Verify the group descriptors....
11796 */
11797 first_block = sb->s_first_data_block;
11798 last_block = first_block + blocks_per_group;
11799
11800 for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
11801 pctx.group = i;
11802
11803 if (i == fs->group_desc_count - 1)
11804 last_block = sb->s_blocks_count;
11805 if ((gd->bg_block_bitmap < first_block) ||
11806 (gd->bg_block_bitmap >= last_block)) {
11807 pctx.blk = gd->bg_block_bitmap;
11808 if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
11809 gd->bg_block_bitmap = 0;
11810 }
11811 if (gd->bg_block_bitmap == 0) {
11812 ctx->invalid_block_bitmap_flag[i]++;
11813 ctx->invalid_bitmaps++;
11814 }
11815 if ((gd->bg_inode_bitmap < first_block) ||
11816 (gd->bg_inode_bitmap >= last_block)) {
11817 pctx.blk = gd->bg_inode_bitmap;
11818 if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
11819 gd->bg_inode_bitmap = 0;
11820 }
11821 if (gd->bg_inode_bitmap == 0) {
11822 ctx->invalid_inode_bitmap_flag[i]++;
11823 ctx->invalid_bitmaps++;
11824 }
11825 if ((gd->bg_inode_table < first_block) ||
11826 ((gd->bg_inode_table +
11827 fs->inode_blocks_per_group - 1) >= last_block)) {
11828 pctx.blk = gd->bg_inode_table;
11829 if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
11830 gd->bg_inode_table = 0;
11831 }
11832 if (gd->bg_inode_table == 0) {
11833 ctx->invalid_inode_table_flag[i]++;
11834 ctx->invalid_bitmaps++;
11835 }
11836 free_blocks += gd->bg_free_blocks_count;
11837 free_inodes += gd->bg_free_inodes_count;
11838 first_block += sb->s_blocks_per_group;
11839 last_block += sb->s_blocks_per_group;
11840
11841 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
11842 (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
11843 (gd->bg_used_dirs_count > sb->s_inodes_per_group))
11844 ext2fs_unmark_valid(fs);
11845
11846 }
11847
11848 /*
11849 * Update the global counts from the block group counts. This
11850 * is needed for an experimental patch which eliminates
11851 * locking the entire filesystem when allocating blocks or
11852 * inodes; if the filesystem is not unmounted cleanly, the
11853 * global counts may not be accurate.
11854 */
11855 if ((free_blocks != sb->s_free_blocks_count) ||
11856 (free_inodes != sb->s_free_inodes_count)) {
11857 if (ctx->options & E2F_OPT_READONLY)
11858 ext2fs_unmark_valid(fs);
11859 else {
11860 sb->s_free_blocks_count = free_blocks;
11861 sb->s_free_inodes_count = free_inodes;
11862 ext2fs_mark_super_dirty(fs);
11863 }
11864 }
11865
11866 if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
11867 (sb->s_free_inodes_count > sb->s_inodes_count))
11868 ext2fs_unmark_valid(fs);
11869
11870
11871 /*
11872 * If we have invalid bitmaps, set the error state of the
11873 * filesystem.
11874 */
11875 if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
11876 sb->s_state &= ~EXT2_VALID_FS;
11877 ext2fs_mark_super_dirty(fs);
11878 }
11879
11880 clear_problem_context(&pctx);
11881
11882 /*
11883 * If the UUID field isn't assigned, assign it.
11884 */
11885 if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
11886 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
11887 uuid_generate(sb->s_uuid);
11888 ext2fs_mark_super_dirty(fs);
11889 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
11890 }
11891 }
11892
11893 /* FIXME - HURD support?
11894 * For the Hurd, check to see if the filetype option is set,
11895 * since it doesn't support it.
11896 */
11897 if (!(ctx->options & E2F_OPT_READONLY) &&
11898 fs->super->s_creator_os == EXT2_OS_HURD &&
11899 (fs->super->s_feature_incompat &
11900 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
11901 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
11902 fs->super->s_feature_incompat &=
11903 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
11904 ext2fs_mark_super_dirty(fs);
11905
11906 }
11907 }
11908
11909 /*
11910 * If we have any of the compatibility flags set, we need to have a
11911 * revision 1 filesystem. Most kernels will not check the flags on
11912 * a rev 0 filesystem and we may have corruption issues because of
11913 * the incompatible changes to the filesystem.
11914 */
11915 if (!(ctx->options & E2F_OPT_READONLY) &&
11916 fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
11917 (fs->super->s_feature_compat ||
11918 fs->super->s_feature_ro_compat ||
11919 fs->super->s_feature_incompat) &&
11920 fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
11921 ext2fs_update_dynamic_rev(fs);
11922 ext2fs_mark_super_dirty(fs);
11923 }
11924
11925 check_resize_inode(ctx);
11926
11927 /*
11928 * Clean up any orphan inodes, if present.
11929 */
11930 if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
11931 fs->super->s_state &= ~EXT2_VALID_FS;
11932 ext2fs_mark_super_dirty(fs);
11933 }
11934
11935 /*
11936 * Move the ext3 journal file, if necessary.
11937 */
11938 e2fsck_move_ext3_journal(ctx);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011939}
11940
11941/*
11942 * swapfs.c --- byte-swap an ext2 filesystem
11943 */
11944
11945#ifdef ENABLE_SWAPFS
11946
11947struct swap_block_struct {
11948 ext2_ino_t ino;
11949 int isdir;
11950 errcode_t errcode;
11951 char *dir_buf;
11952 struct ext2_inode *inode;
11953};
11954
11955/*
11956 * This is a helper function for block_iterate. We mark all of the
11957 * indirect and direct blocks as changed, so that block_iterate will
11958 * write them out.
11959 */
11960static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
11961 void *priv_data)
11962{
11963 errcode_t retval;
11964
11965 struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
11966
11967 if (sb->isdir && (blockcnt >= 0) && *block_nr) {
11968 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
11969 if (retval) {
11970 sb->errcode = retval;
11971 return BLOCK_ABORT;
11972 }
11973 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
11974 if (retval) {
11975 sb->errcode = retval;
11976 return BLOCK_ABORT;
11977 }
11978 }
11979 if (blockcnt >= 0) {
11980 if (blockcnt < EXT2_NDIR_BLOCKS)
11981 return 0;
11982 return BLOCK_CHANGED;
11983 }
11984 if (blockcnt == BLOCK_COUNT_IND) {
11985 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
11986 return 0;
11987 return BLOCK_CHANGED;
11988 }
11989 if (blockcnt == BLOCK_COUNT_DIND) {
11990 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
11991 return 0;
11992 return BLOCK_CHANGED;
11993 }
11994 if (blockcnt == BLOCK_COUNT_TIND) {
11995 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
11996 return 0;
11997 return BLOCK_CHANGED;
11998 }
11999 return BLOCK_CHANGED;
12000}
12001
12002/*
12003 * This function is responsible for byte-swapping all of the indirect,
12004 * block pointers. It is also responsible for byte-swapping directories.
12005 */
12006static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
12007 struct ext2_inode *inode)
12008{
12009 errcode_t retval;
12010 struct swap_block_struct sb;
12011
12012 sb.ino = ino;
12013 sb.inode = inode;
12014 sb.dir_buf = block_buf + ctx->fs->blocksize*3;
12015 sb.errcode = 0;
12016 sb.isdir = 0;
12017 if (LINUX_S_ISDIR(inode->i_mode))
12018 sb.isdir = 1;
12019
12020 retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
12021 swap_block, &sb);
12022 if (retval) {
12023 bb_error_msg(_("while calling ext2fs_block_iterate"));
12024 ctx->flags |= E2F_FLAG_ABORT;
12025 return;
12026 }
12027 if (sb.errcode) {
12028 bb_error_msg(_("while calling iterator function"));
12029 ctx->flags |= E2F_FLAG_ABORT;
12030 return;
12031 }
12032}
12033
12034static void swap_inodes(e2fsck_t ctx)
12035{
12036 ext2_filsys fs = ctx->fs;
12037 dgrp_t group;
12038 unsigned int i;
12039 ext2_ino_t ino = 1;
12040 char *buf, *block_buf;
12041 errcode_t retval;
12042 struct ext2_inode * inode;
12043
12044 e2fsck_use_inode_shortcuts(ctx, 1);
12045
12046 retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
12047 &buf);
12048 if (retval) {
12049 bb_error_msg(_("while allocating inode buffer"));
12050 ctx->flags |= E2F_FLAG_ABORT;
12051 return;
12052 }
12053 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12054 "block interate buffer");
12055 for (group = 0; group < fs->group_desc_count; group++) {
12056 retval = io_channel_read_blk(fs->io,
12057 fs->group_desc[group].bg_inode_table,
12058 fs->inode_blocks_per_group, buf);
12059 if (retval) {
12060 bb_error_msg(_("while reading inode table (group %d)"),
12061 group);
12062 ctx->flags |= E2F_FLAG_ABORT;
12063 return;
12064 }
12065 inode = (struct ext2_inode *) buf;
12066 for (i=0; i < fs->super->s_inodes_per_group;
12067 i++, ino++, inode++) {
12068 ctx->stashed_ino = ino;
12069 ctx->stashed_inode = inode;
12070
12071 if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
12072 ext2fs_swap_inode(fs, inode, inode, 0);
12073
12074 /*
12075 * Skip deleted files.
12076 */
12077 if (inode->i_links_count == 0)
12078 continue;
12079
12080 if (LINUX_S_ISDIR(inode->i_mode) ||
12081 ((inode->i_block[EXT2_IND_BLOCK] ||
12082 inode->i_block[EXT2_DIND_BLOCK] ||
12083 inode->i_block[EXT2_TIND_BLOCK]) &&
12084 ext2fs_inode_has_valid_blocks(inode)))
12085 swap_inode_blocks(ctx, ino, block_buf, inode);
12086
12087 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12088 return;
12089
12090 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12091 ext2fs_swap_inode(fs, inode, inode, 1);
12092 }
12093 retval = io_channel_write_blk(fs->io,
12094 fs->group_desc[group].bg_inode_table,
12095 fs->inode_blocks_per_group, buf);
12096 if (retval) {
12097 bb_error_msg(_("while writing inode table (group %d)"),
12098 group);
12099 ctx->flags |= E2F_FLAG_ABORT;
12100 return;
12101 }
12102 }
12103 ext2fs_free_mem(&buf);
12104 ext2fs_free_mem(&block_buf);
12105 e2fsck_use_inode_shortcuts(ctx, 0);
12106 ext2fs_flush_icache(fs);
12107}
12108
12109#if defined(__powerpc__) && BB_BIG_ENDIAN
12110/*
12111 * On the PowerPC, the big-endian variant of the ext2 filesystem
12112 * has its bitmaps stored as 32-bit words with bit 0 as the LSB
12113 * of each word. Thus a bitmap with only bit 0 set would be, as
12114 * a string of bytes, 00 00 00 01 00 ...
12115 * To cope with this, we byte-reverse each word of a bitmap if
12116 * we have a big-endian filesystem, that is, if we are *not*
12117 * byte-swapping other word-sized numbers.
12118 */
12119#define EXT2_BIG_ENDIAN_BITMAPS
12120#endif
12121
12122#ifdef EXT2_BIG_ENDIAN_BITMAPS
12123static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
12124{
12125 __u32 *p = (__u32 *) bmap->bitmap;
12126 int n, nbytes = (bmap->end - bmap->start + 7) / 8;
12127
12128 for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
12129 *p = ext2fs_swab32(*p);
12130}
12131#endif
12132
12133
12134#ifdef ENABLE_SWAPFS
12135static void swap_filesys(e2fsck_t ctx)
12136{
12137 ext2_filsys fs = ctx->fs;
12138 if (!(ctx->options & E2F_OPT_PREEN))
12139 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
12140
12141 /* Byte swap */
12142
12143 if (fs->super->s_mnt_count) {
12144 fprintf(stderr, _("%s: the filesystem must be freshly "
12145 "checked using fsck\n"
12146 "and not mounted before trying to "
12147 "byte-swap it.\n"), ctx->device_name);
12148 ctx->flags |= E2F_FLAG_ABORT;
12149 return;
12150 }
12151 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
12152 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
12153 EXT2_FLAG_SWAP_BYTES_WRITE);
12154 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
12155 } else {
12156 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
12157 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
12158 }
12159 swap_inodes(ctx);
12160 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12161 return;
12162 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12163 fs->flags |= EXT2_FLAG_SWAP_BYTES;
12164 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
12165 EXT2_FLAG_SWAP_BYTES_WRITE);
12166
12167#ifdef EXT2_BIG_ENDIAN_BITMAPS
12168 e2fsck_read_bitmaps(ctx);
12169 ext2fs_swap_bitmap(fs->inode_map);
12170 ext2fs_swap_bitmap(fs->block_map);
12171 fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
12172#endif
12173 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
12174 ext2fs_flush(fs);
12175 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
12176}
12177#endif /* ENABLE_SWAPFS */
12178
12179#endif
12180
12181/*
12182 * util.c --- miscellaneous utilities
12183 */
12184
12185
12186void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
12187 const char *description)
12188{
12189 void *ret;
12190 char buf[256];
12191
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010012192 ret = xzalloc(size);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012193 return ret;
12194}
12195
12196static char *string_copy(const char *str, int len)
12197{
12198 char *ret;
12199
12200 if (!str)
12201 return NULL;
12202 if (!len)
12203 len = strlen(str);
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010012204 ret = xmalloc(len+1);
12205 strncpy(ret, str, len);
12206 ret[len] = 0;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012207 return ret;
12208}
12209
12210#ifndef HAVE_CONIO_H
12211static int read_a_char(void)
12212{
12213 char c;
12214 int r;
12215 int fail = 0;
12216
Denis Vlasenkobb045062008-09-27 14:06:06 +000012217 while (1) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012218 if (e2fsck_global_ctx &&
12219 (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
12220 return 3;
12221 }
12222 r = read(0, &c, 1);
12223 if (r == 1)
12224 return c;
12225 if (fail++ > 100)
12226 break;
12227 }
12228 return EOF;
12229}
12230#endif
12231
12232static int ask_yn(const char * string, int def)
12233{
12234 int c;
12235 const char *defstr;
12236 static const char short_yes[] = "yY";
12237 static const char short_no[] = "nN";
12238
12239#ifdef HAVE_TERMIOS_H
12240 struct termios termios, tmp;
12241
12242 tcgetattr (0, &termios);
12243 tmp = termios;
12244 tmp.c_lflag &= ~(ICANON | ECHO);
12245 tmp.c_cc[VMIN] = 1;
12246 tmp.c_cc[VTIME] = 0;
Denis Vlasenko202ac502008-11-05 13:20:58 +000012247 tcsetattr_stdin_TCSANOW(&tmp);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012248#endif
12249
12250 if (def == 1)
12251 defstr = "<y>";
12252 else if (def == 0)
12253 defstr = "<n>";
12254 else
12255 defstr = " (y/n)";
12256 printf("%s%s? ", string, defstr);
12257 while (1) {
12258 fflush (stdout);
12259 if ((c = read_a_char()) == EOF)
12260 break;
12261 if (c == 3) {
12262#ifdef HAVE_TERMIOS_H
Denis Vlasenko202ac502008-11-05 13:20:58 +000012263 tcsetattr_stdin_TCSANOW(&termios);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012264#endif
12265 if (e2fsck_global_ctx &&
12266 e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
12267 puts("\n");
12268 longjmp(e2fsck_global_ctx->abort_loc, 1);
12269 }
12270 puts(_("cancelled!\n"));
12271 return 0;
12272 }
12273 if (strchr(short_yes, (char) c)) {
12274 def = 1;
12275 break;
12276 }
12277 else if (strchr(short_no, (char) c)) {
12278 def = 0;
12279 break;
12280 }
12281 else if ((c == ' ' || c == '\n') && (def != -1))
12282 break;
12283 }
12284 if (def)
12285 puts("yes\n");
12286 else
12287 puts ("no\n");
12288#ifdef HAVE_TERMIOS_H
Denis Vlasenko202ac502008-11-05 13:20:58 +000012289 tcsetattr_stdin_TCSANOW(&termios);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012290#endif
12291 return def;
12292}
12293
12294int ask (e2fsck_t ctx, const char * string, int def)
12295{
12296 if (ctx->options & E2F_OPT_NO) {
12297 printf(_("%s? no\n\n"), string);
12298 return 0;
12299 }
12300 if (ctx->options & E2F_OPT_YES) {
12301 printf(_("%s? yes\n\n"), string);
12302 return 1;
12303 }
12304 if (ctx->options & E2F_OPT_PREEN) {
12305 printf("%s? %s\n\n", string, def ? _("yes") : _("no"));
12306 return def;
12307 }
12308 return ask_yn(string, def);
12309}
12310
12311void e2fsck_read_bitmaps(e2fsck_t ctx)
12312{
12313 ext2_filsys fs = ctx->fs;
12314 errcode_t retval;
12315
12316 if (ctx->invalid_bitmaps) {
12317 bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12318 ctx->device_name);
12319 bb_error_msg_and_die(0);
12320 }
12321
12322 ehandler_operation(_("reading inode and block bitmaps"));
12323 retval = ext2fs_read_bitmaps(fs);
12324 ehandler_operation(0);
12325 if (retval) {
12326 bb_error_msg(_("while retrying to read bitmaps for %s"),
12327 ctx->device_name);
12328 bb_error_msg_and_die(0);
12329 }
12330}
12331
12332static void e2fsck_write_bitmaps(e2fsck_t ctx)
12333{
12334 ext2_filsys fs = ctx->fs;
12335 errcode_t retval;
12336
12337 if (ext2fs_test_bb_dirty(fs)) {
12338 ehandler_operation(_("writing block bitmaps"));
12339 retval = ext2fs_write_block_bitmap(fs);
12340 ehandler_operation(0);
12341 if (retval) {
12342 bb_error_msg(_("while retrying to write block bitmaps for %s"),
12343 ctx->device_name);
12344 bb_error_msg_and_die(0);
12345 }
12346 }
12347
12348 if (ext2fs_test_ib_dirty(fs)) {
12349 ehandler_operation(_("writing inode bitmaps"));
12350 retval = ext2fs_write_inode_bitmap(fs);
12351 ehandler_operation(0);
12352 if (retval) {
12353 bb_error_msg(_("while retrying to write inode bitmaps for %s"),
12354 ctx->device_name);
12355 bb_error_msg_and_die(0);
12356 }
12357 }
12358}
12359
12360void preenhalt(e2fsck_t ctx)
12361{
12362 ext2_filsys fs = ctx->fs;
12363
12364 if (!(ctx->options & E2F_OPT_PREEN))
12365 return;
12366 fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12367 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12368 ctx->device_name);
12369 if (fs != NULL) {
12370 fs->super->s_state |= EXT2_ERROR_FS;
12371 ext2fs_mark_super_dirty(fs);
12372 ext2fs_close(fs);
12373 }
12374 exit(EXIT_UNCORRECTED);
12375}
12376
12377void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12378 struct ext2_inode * inode, const char *proc)
12379{
12380 int retval;
12381
12382 retval = ext2fs_read_inode(ctx->fs, ino, inode);
12383 if (retval) {
12384 bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
12385 bb_error_msg_and_die(0);
12386 }
12387}
12388
12389extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12390 struct ext2_inode * inode, int bufsize,
12391 const char *proc)
12392{
12393 int retval;
12394
12395 retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12396 if (retval) {
12397 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12398 bb_error_msg_and_die(0);
12399 }
12400}
12401
12402extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12403 struct ext2_inode * inode, const char *proc)
12404{
12405 int retval;
12406
12407 retval = ext2fs_write_inode(ctx->fs, ino, inode);
12408 if (retval) {
12409 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12410 bb_error_msg_and_die(0);
12411 }
12412}
12413
12414blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12415 io_manager manager)
12416{
12417 struct ext2_super_block *sb;
12418 io_channel io = NULL;
12419 void *buf = NULL;
12420 int blocksize;
12421 blk_t superblock, ret_sb = 8193;
12422
12423 if (fs && fs->super) {
12424 ret_sb = (fs->super->s_blocks_per_group +
12425 fs->super->s_first_data_block);
12426 if (ctx) {
12427 ctx->superblock = ret_sb;
12428 ctx->blocksize = fs->blocksize;
12429 }
12430 return ret_sb;
12431 }
12432
12433 if (ctx) {
12434 if (ctx->blocksize) {
12435 ret_sb = ctx->blocksize * 8;
12436 if (ctx->blocksize == 1024)
12437 ret_sb++;
12438 ctx->superblock = ret_sb;
12439 return ret_sb;
12440 }
12441 ctx->superblock = ret_sb;
12442 ctx->blocksize = 1024;
12443 }
12444
12445 if (!name || !manager)
12446 goto cleanup;
12447
12448 if (manager->open(name, 0, &io) != 0)
12449 goto cleanup;
12450
12451 if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12452 goto cleanup;
12453 sb = (struct ext2_super_block *) buf;
12454
12455 for (blocksize = EXT2_MIN_BLOCK_SIZE;
Denis Vlasenkob71c6682007-07-21 15:08:09 +000012456 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012457 superblock = blocksize*8;
12458 if (blocksize == 1024)
12459 superblock++;
12460 io_channel_set_blksize(io, blocksize);
12461 if (io_channel_read_blk(io, superblock,
12462 -SUPERBLOCK_SIZE, buf))
12463 continue;
12464#if BB_BIG_ENDIAN
12465 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12466 ext2fs_swap_super(sb);
12467#endif
12468 if (sb->s_magic == EXT2_SUPER_MAGIC) {
12469 ret_sb = superblock;
12470 if (ctx) {
12471 ctx->superblock = superblock;
12472 ctx->blocksize = blocksize;
12473 }
12474 break;
12475 }
12476 }
12477
12478cleanup:
12479 if (io)
12480 io_channel_close(io);
12481 ext2fs_free_mem(&buf);
12482 return ret_sb;
12483}
12484
12485
12486/*
12487 * This function runs through the e2fsck passes and calls them all,
12488 * returning restart, abort, or cancel as necessary...
12489 */
12490typedef void (*pass_t)(e2fsck_t ctx);
12491
12492static const pass_t e2fsck_passes[] = {
12493 e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12494 e2fsck_pass5, 0 };
12495
12496#define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12497
12498static int e2fsck_run(e2fsck_t ctx)
12499{
12500 int i;
12501 pass_t e2fsck_pass;
12502
12503 if (setjmp(ctx->abort_loc)) {
12504 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12505 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12506 }
12507 ctx->flags |= E2F_FLAG_SETJMP_OK;
12508
12509 for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12510 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12511 break;
12512 e2fsck_pass(ctx);
12513 if (ctx->progress)
12514 (void) (ctx->progress)(ctx, 0, 0, 0);
12515 }
12516 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12517
12518 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12519 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12520 return 0;
12521}
12522
12523
12524/*
12525 * unix.c - The unix-specific code for e2fsck
12526 */
12527
12528
12529/* Command line options */
12530static int swapfs;
12531#ifdef ENABLE_SWAPFS
12532static int normalize_swapfs;
12533#endif
12534static int cflag; /* check disk */
12535static int show_version_only;
12536static int verbose;
12537
12538#define P_E2(singular, plural, n) n, ((n) == 1 ? singular : plural)
12539
12540static void show_stats(e2fsck_t ctx)
12541{
12542 ext2_filsys fs = ctx->fs;
12543 int inodes, inodes_used, blocks, blocks_used;
12544 int dir_links;
12545 int num_files, num_links;
12546 int frag_percent;
12547
12548 dir_links = 2 * ctx->fs_directory_count - 1;
12549 num_files = ctx->fs_total_count - dir_links;
12550 num_links = ctx->fs_links_count - dir_links;
12551 inodes = fs->super->s_inodes_count;
12552 inodes_used = (fs->super->s_inodes_count -
12553 fs->super->s_free_inodes_count);
12554 blocks = fs->super->s_blocks_count;
12555 blocks_used = (fs->super->s_blocks_count -
12556 fs->super->s_free_blocks_count);
12557
12558 frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12559 frag_percent = (frag_percent + 5) / 10;
12560
12561 if (!verbose) {
12562 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12563 ctx->device_name, inodes_used, inodes,
12564 frag_percent / 10, frag_percent % 10,
12565 blocks_used, blocks);
12566 return;
12567 }
12568 printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12569 100 * inodes_used / inodes);
12570 printf("%8d non-contiguous inode%s (%0d.%d%%)\n",
12571 P_E2("", "s", ctx->fs_fragmented),
12572 frag_percent / 10, frag_percent % 10);
12573 printf(_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12574 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12575 printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12576 (int) ((long long) 100 * blocks_used / blocks));
12577 printf("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12578 printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12579 printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12580 printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12581 printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12582 printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12583 printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12584 printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12585 printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12586 printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12587 printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12588}
12589
12590static void check_mount(e2fsck_t ctx)
12591{
12592 errcode_t retval;
12593 int cont;
12594
12595 retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12596 &ctx->mount_flags);
12597 if (retval) {
Denis Vlasenko54d10052008-12-24 03:11:43 +000012598 bb_error_msg(_("while determining whether %s is mounted"),
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012599 ctx->filesystem_name);
12600 return;
12601 }
12602
12603 /*
12604 * If the filesystem isn't mounted, or it's the root filesystem
12605 * and it's mounted read-only, then everything's fine.
12606 */
12607 if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12608 ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12609 (ctx->mount_flags & EXT2_MF_READONLY)))
12610 return;
12611
12612 if (ctx->options & E2F_OPT_READONLY) {
12613 printf(_("Warning! %s is mounted.\n"), ctx->filesystem_name);
12614 return;
12615 }
12616
12617 printf(_("%s is mounted. "), ctx->filesystem_name);
12618 if (!ctx->interactive)
Denys Vlasenko6331cf02009-11-13 09:08:27 +010012619 bb_error_msg_and_die(_("can't continue, aborting"));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012620 printf(_("\n\n\007\007\007\007WARNING!!! "
12621 "Running e2fsck on a mounted filesystem may cause\n"
12622 "SEVERE filesystem damage.\007\007\007\n\n"));
12623 cont = ask_yn(_("Do you really want to continue"), -1);
12624 if (!cont) {
12625 printf(_("check aborted.\n"));
Denis Vlasenko6398cf42007-04-11 17:04:29 +000012626 exit(0);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012627 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012628}
12629
12630static int is_on_batt(void)
12631{
12632 FILE *f;
12633 DIR *d;
12634 char tmp[80], tmp2[80], fname[80];
12635 unsigned int acflag;
12636 struct dirent* de;
12637
Denis Vlasenko5415c852008-07-21 23:05:26 +000012638 f = fopen_for_read("/proc/apm");
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012639 if (f) {
12640 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12641 acflag = 1;
12642 fclose(f);
12643 return (acflag != 1);
12644 }
12645 d = opendir("/proc/acpi/ac_adapter");
12646 if (d) {
12647 while ((de=readdir(d)) != NULL) {
12648 if (!strncmp(".", de->d_name, 1))
12649 continue;
12650 snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12651 de->d_name);
Denis Vlasenko5415c852008-07-21 23:05:26 +000012652 f = fopen_for_read(fname);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012653 if (!f)
12654 continue;
12655 if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12656 tmp[0] = 0;
12657 fclose(f);
12658 if (strncmp(tmp, "off-line", 8) == 0) {
12659 closedir(d);
12660 return 1;
12661 }
12662 }
12663 closedir(d);
12664 }
12665 return 0;
12666}
12667
12668/*
12669 * This routine checks to see if a filesystem can be skipped; if so,
12670 * it will exit with EXIT_OK. Under some conditions it will print a
12671 * message explaining why a check is being forced.
12672 */
12673static void check_if_skip(e2fsck_t ctx)
12674{
12675 ext2_filsys fs = ctx->fs;
12676 const char *reason = NULL;
12677 unsigned int reason_arg = 0;
12678 long next_check;
12679 int batt = is_on_batt();
Denis Vlasenko04158e02009-02-02 10:48:06 +000012680 time_t now = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012681
12682 if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12683 return;
12684
12685 if ((fs->super->s_state & EXT2_ERROR_FS) ||
12686 !ext2fs_test_valid(fs))
12687 reason = _(" contains a file system with errors");
12688 else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12689 reason = _(" was not cleanly unmounted");
12690 else if ((fs->super->s_max_mnt_count > 0) &&
12691 (fs->super->s_mnt_count >=
12692 (unsigned) fs->super->s_max_mnt_count)) {
12693 reason = _(" has been mounted %u times without being checked");
12694 reason_arg = fs->super->s_mnt_count;
12695 if (batt && (fs->super->s_mnt_count <
12696 (unsigned) fs->super->s_max_mnt_count*2))
12697 reason = 0;
12698 } else if (fs->super->s_checkinterval &&
12699 ((now - fs->super->s_lastcheck) >=
12700 fs->super->s_checkinterval)) {
12701 reason = _(" has gone %u days without being checked");
12702 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12703 if (batt && ((now - fs->super->s_lastcheck) <
12704 fs->super->s_checkinterval*2))
12705 reason = 0;
12706 }
12707 if (reason) {
12708 fputs(ctx->device_name, stdout);
12709 printf(reason, reason_arg);
12710 fputs(_(", check forced.\n"), stdout);
12711 return;
12712 }
12713 printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12714 fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12715 fs->super->s_inodes_count,
12716 fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12717 fs->super->s_blocks_count);
12718 next_check = 100000;
12719 if (fs->super->s_max_mnt_count > 0) {
12720 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12721 if (next_check <= 0)
12722 next_check = 1;
12723 }
12724 if (fs->super->s_checkinterval &&
12725 ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12726 next_check = 1;
12727 if (next_check <= 5) {
12728 if (next_check == 1)
12729 fputs(_(" (check after next mount)"), stdout);
12730 else
12731 printf(_(" (check in %ld mounts)"), next_check);
12732 }
Denis Vlasenko4daad902007-09-27 10:20:47 +000012733 bb_putchar('\n');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012734 ext2fs_close(fs);
12735 ctx->fs = NULL;
12736 e2fsck_free_context(ctx);
12737 exit(EXIT_OK);
12738}
12739
12740/*
12741 * For completion notice
12742 */
12743struct percent_tbl {
12744 int max_pass;
12745 int table[32];
12746};
12747static const struct percent_tbl e2fsck_tbl = {
12748 5, { 0, 70, 90, 92, 95, 100 }
12749};
12750
12751static char bar[128], spaces[128];
12752
12753static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12754 int max)
12755{
12756 float percent;
12757
12758 if (pass <= 0)
12759 return 0.0;
12760 if (pass > tbl->max_pass || max == 0)
12761 return 100.0;
12762 percent = ((float) curr) / ((float) max);
12763 return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12764 + tbl->table[pass-1]);
12765}
12766
12767void e2fsck_clear_progbar(e2fsck_t ctx)
12768{
12769 if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12770 return;
12771
12772 printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12773 ctx->stop_meta);
12774 fflush(stdout);
12775 ctx->flags &= ~E2F_FLAG_PROG_BAR;
12776}
12777
12778int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12779 unsigned int dpynum)
12780{
12781 static const char spinner[] = "\\|/-";
12782 int i;
12783 unsigned int tick;
12784 struct timeval tv;
12785 int dpywidth;
12786 int fixed_percent;
12787
12788 if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12789 return 0;
12790
12791 /*
12792 * Calculate the new progress position. If the
12793 * percentage hasn't changed, then we skip out right
12794 * away.
12795 */
12796 fixed_percent = (int) ((10 * percent) + 0.5);
12797 if (ctx->progress_last_percent == fixed_percent)
12798 return 0;
12799 ctx->progress_last_percent = fixed_percent;
12800
12801 /*
12802 * If we've already updated the spinner once within
12803 * the last 1/8th of a second, no point doing it
12804 * again.
12805 */
12806 gettimeofday(&tv, NULL);
12807 tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12808 if ((tick == ctx->progress_last_time) &&
12809 (fixed_percent != 0) && (fixed_percent != 1000))
12810 return 0;
12811 ctx->progress_last_time = tick;
12812
12813 /*
12814 * Advance the spinner, and note that the progress bar
12815 * will be on the screen
12816 */
12817 ctx->progress_pos = (ctx->progress_pos+1) & 3;
12818 ctx->flags |= E2F_FLAG_PROG_BAR;
12819
12820 dpywidth = 66 - strlen(label);
12821 dpywidth = 8 * (dpywidth / 8);
12822 if (dpynum)
12823 dpywidth -= 8;
12824
12825 i = ((percent * dpywidth) + 50) / 100;
12826 printf("%s%s: |%s%s", ctx->start_meta, label,
12827 bar + (sizeof(bar) - (i+1)),
12828 spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12829 if (fixed_percent == 1000)
Denis Vlasenko4daad902007-09-27 10:20:47 +000012830 bb_putchar('|');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012831 else
Denis Vlasenko4daad902007-09-27 10:20:47 +000012832 bb_putchar(spinner[ctx->progress_pos & 3]);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012833 printf(" %4.1f%% ", percent);
12834 if (dpynum)
12835 printf("%u\r", dpynum);
12836 else
12837 fputs(" \r", stdout);
12838 fputs(ctx->stop_meta, stdout);
12839
12840 if (fixed_percent == 1000)
12841 e2fsck_clear_progbar(ctx);
12842 fflush(stdout);
12843
12844 return 0;
12845}
12846
12847static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12848 unsigned long cur, unsigned long max)
12849{
12850 char buf[80];
12851 float percent;
12852
12853 if (pass == 0)
12854 return 0;
12855
12856 if (ctx->progress_fd) {
12857 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
Denis Vlasenko73c571a2009-03-09 00:12:37 +000012858 xwrite_str(ctx->progress_fd, buf);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012859 } else {
12860 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12861 e2fsck_simple_progress(ctx, ctx->device_name,
12862 percent, 0);
12863 }
12864 return 0;
12865}
12866
12867static void reserve_stdio_fds(void)
12868{
12869 int fd;
12870
12871 while (1) {
12872 fd = open(bb_dev_null, O_RDWR);
12873 if (fd > 2)
12874 break;
12875 if (fd < 0) {
12876 fprintf(stderr, _("ERROR: Cannot open "
12877 "/dev/null (%s)\n"),
12878 strerror(errno));
12879 break;
12880 }
12881 }
12882 close(fd);
12883}
12884
12885static void signal_progress_on(int sig FSCK_ATTR((unused)))
12886{
12887 e2fsck_t ctx = e2fsck_global_ctx;
12888
12889 if (!ctx)
12890 return;
12891
12892 ctx->progress = e2fsck_update_progress;
12893 ctx->progress_fd = 0;
12894}
12895
12896static void signal_progress_off(int sig FSCK_ATTR((unused)))
12897{
12898 e2fsck_t ctx = e2fsck_global_ctx;
12899
12900 if (!ctx)
12901 return;
12902
12903 e2fsck_clear_progbar(ctx);
12904 ctx->progress = 0;
12905}
12906
12907static void signal_cancel(int sig FSCK_ATTR((unused)))
12908{
12909 e2fsck_t ctx = e2fsck_global_ctx;
12910
12911 if (!ctx)
12912 exit(FSCK_CANCELED);
12913
12914 ctx->flags |= E2F_FLAG_CANCEL;
12915}
12916
12917static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12918{
12919 char *buf, *token, *next, *p, *arg;
12920 int ea_ver;
12921 int extended_usage = 0;
12922
12923 buf = string_copy(opts, 0);
12924 for (token = buf; token && *token; token = next) {
12925 p = strchr(token, ',');
12926 next = 0;
12927 if (p) {
12928 *p = 0;
12929 next = p+1;
12930 }
12931 arg = strchr(token, '=');
12932 if (arg) {
12933 *arg = 0;
12934 arg++;
12935 }
12936 if (strcmp(token, "ea_ver") == 0) {
12937 if (!arg) {
12938 extended_usage++;
12939 continue;
12940 }
12941 ea_ver = strtoul(arg, &p, 0);
12942 if (*p ||
12943 ((ea_ver != 1) && (ea_ver != 2))) {
12944 fprintf(stderr,
12945 _("Invalid EA version.\n"));
12946 extended_usage++;
12947 continue;
12948 }
12949 ctx->ext_attr_ver = ea_ver;
12950 } else {
12951 fprintf(stderr, _("Unknown extended option: %s\n"),
12952 token);
12953 extended_usage++;
12954 }
12955 }
12956 if (extended_usage) {
12957 bb_error_msg_and_die(
12958 "Extended options are separated by commas, "
12959 "and may take an argument which\n"
12960 "is set off by an equals ('=') sign. "
12961 "Valid extended options are:\n"
12962 "\tea_ver=<ea_version (1 or 2)>\n\n");
12963 }
12964}
12965
12966
Bernhard Reutner-Fischerfebe3c42007-04-04 20:52:03 +000012967static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012968{
12969 int flush = 0;
12970 int c, fd;
12971 e2fsck_t ctx;
12972 errcode_t retval;
12973 struct sigaction sa;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +010012974 char *extended_opts = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012975
12976 retval = e2fsck_allocate_context(&ctx);
12977 if (retval)
12978 return retval;
12979
12980 *ret_ctx = ctx;
12981
12982 setvbuf(stdout, NULL, _IONBF, BUFSIZ);
12983 setvbuf(stderr, NULL, _IONBF, BUFSIZ);
12984 if (isatty(0) && isatty(1)) {
12985 ctx->interactive = 1;
12986 } else {
12987 ctx->start_meta[0] = '\001';
12988 ctx->stop_meta[0] = '\002';
12989 }
12990 memset(bar, '=', sizeof(bar)-1);
12991 memset(spaces, ' ', sizeof(spaces)-1);
12992 blkid_get_cache(&ctx->blkid, NULL);
12993
12994 if (argc && *argv)
12995 ctx->program_name = *argv;
12996 else
12997 ctx->program_name = "e2fsck";
12998 while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
12999 switch (c) {
13000 case 'C':
13001 ctx->progress = e2fsck_update_progress;
13002 ctx->progress_fd = atoi(optarg);
13003 if (!ctx->progress_fd)
13004 break;
13005 /* Validate the file descriptor to avoid disasters */
13006 fd = dup(ctx->progress_fd);
13007 if (fd < 0) {
13008 fprintf(stderr,
13009 _("Error validating file descriptor %d: %s\n"),
13010 ctx->progress_fd,
13011 error_message(errno));
13012 bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13013 } else
13014 close(fd);
13015 break;
13016 case 'D':
13017 ctx->options |= E2F_OPT_COMPRESS_DIRS;
13018 break;
13019 case 'E':
13020 extended_opts = optarg;
13021 break;
13022 case 'p':
13023 case 'a':
13024 if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13025 conflict_opt:
Denis Vlasenko54d10052008-12-24 03:11:43 +000013026 bb_error_msg_and_die(_("only one the options -p/-a, -n or -y may be specified"));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013027 }
13028 ctx->options |= E2F_OPT_PREEN;
13029 break;
13030 case 'n':
13031 if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13032 goto conflict_opt;
13033 ctx->options |= E2F_OPT_NO;
13034 break;
13035 case 'y':
13036 if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13037 goto conflict_opt;
13038 ctx->options |= E2F_OPT_YES;
13039 break;
13040 case 't':
13041 /* FIXME - This needs to go away in a future path - will change binary */
13042 fprintf(stderr, _("The -t option is not "
13043 "supported on this version of e2fsck.\n"));
13044 break;
13045 case 'c':
13046 if (cflag++)
13047 ctx->options |= E2F_OPT_WRITECHECK;
13048 ctx->options |= E2F_OPT_CHECKBLOCKS;
13049 break;
13050 case 'r':
13051 /* What we do by default, anyway! */
13052 break;
13053 case 'b':
13054 ctx->use_superblock = atoi(optarg);
13055 ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13056 break;
13057 case 'B':
13058 ctx->blocksize = atoi(optarg);
13059 break;
13060 case 'I':
13061 ctx->inode_buffer_blocks = atoi(optarg);
13062 break;
13063 case 'j':
13064 ctx->journal_name = string_copy(optarg, 0);
13065 break;
13066 case 'P':
13067 ctx->process_inode_size = atoi(optarg);
13068 break;
13069 case 'd':
13070 ctx->options |= E2F_OPT_DEBUG;
13071 break;
13072 case 'f':
13073 ctx->options |= E2F_OPT_FORCE;
13074 break;
13075 case 'F':
13076 flush = 1;
13077 break;
13078 case 'v':
13079 verbose = 1;
13080 break;
13081 case 'V':
13082 show_version_only = 1;
13083 break;
13084 case 'N':
13085 ctx->device_name = optarg;
13086 break;
13087#ifdef ENABLE_SWAPFS
13088 case 's':
13089 normalize_swapfs = 1;
13090 case 'S':
13091 swapfs = 1;
13092 break;
13093#else
13094 case 's':
13095 case 'S':
13096 fprintf(stderr, _("Byte-swapping filesystems "
13097 "not compiled in this version "
13098 "of e2fsck\n"));
13099 exit(1);
13100#endif
13101 default:
13102 bb_show_usage();
13103 }
13104 if (show_version_only)
13105 return 0;
13106 if (optind != argc - 1)
13107 bb_show_usage();
13108 if ((ctx->options & E2F_OPT_NO) &&
13109 !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13110 ctx->options |= E2F_OPT_READONLY;
13111 ctx->io_options = strchr(argv[optind], '?');
13112 if (ctx->io_options)
13113 *ctx->io_options++ = 0;
13114 ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
13115 if (!ctx->filesystem_name) {
13116 bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
13117 bb_error_msg_and_die(0);
13118 }
13119 if (extended_opts)
13120 parse_extended_opts(ctx, extended_opts);
13121
13122 if (flush) {
13123 fd = open(ctx->filesystem_name, O_RDONLY, 0);
13124 if (fd < 0) {
13125 bb_error_msg(_("while opening %s for flushing"),
13126 ctx->filesystem_name);
13127 bb_error_msg_and_die(0);
13128 }
13129 if ((retval = ext2fs_sync_device(fd, 1))) {
13130 bb_error_msg(_("while trying to flush %s"),
13131 ctx->filesystem_name);
13132 bb_error_msg_and_die(0);
13133 }
13134 close(fd);
13135 }
13136#ifdef ENABLE_SWAPFS
13137 if (swapfs && cflag) {
13138 fprintf(stderr, _("Incompatible options not "
13139 "allowed when byte-swapping.\n"));
13140 exit(EXIT_USAGE);
13141 }
13142#endif
13143 /*
13144 * Set up signal action
13145 */
13146 memset(&sa, 0, sizeof(struct sigaction));
13147 sa.sa_handler = signal_cancel;
13148 sigaction(SIGINT, &sa, 0);
13149 sigaction(SIGTERM, &sa, 0);
13150#ifdef SA_RESTART
13151 sa.sa_flags = SA_RESTART;
13152#endif
13153 e2fsck_global_ctx = ctx;
13154 sa.sa_handler = signal_progress_on;
13155 sigaction(SIGUSR1, &sa, 0);
13156 sa.sa_handler = signal_progress_off;
13157 sigaction(SIGUSR2, &sa, 0);
13158
13159 /* Update our PATH to include /sbin if we need to run badblocks */
13160 if (cflag)
13161 e2fs_set_sbin_path();
13162 return 0;
13163}
13164
13165static const char my_ver_string[] = E2FSPROGS_VERSION;
13166static const char my_ver_date[] = E2FSPROGS_DATE;
13167
Bernhard Reutner-Fischerfebe3c42007-04-04 20:52:03 +000013168int e2fsck_main (int argc, char **argv);
13169int e2fsck_main (int argc, char **argv)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013170{
13171 errcode_t retval;
13172 int exit_value = EXIT_OK;
13173 ext2_filsys fs = 0;
13174 io_manager io_ptr;
13175 struct ext2_super_block *sb;
13176 const char *lib_ver_date;
13177 int my_ver, lib_ver;
13178 e2fsck_t ctx;
13179 struct problem_context pctx;
13180 int flags, run_result;
13181
13182 clear_problem_context(&pctx);
13183
13184 my_ver = ext2fs_parse_version_string(my_ver_string);
13185 lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13186 if (my_ver > lib_ver) {
13187 fprintf( stderr, _("Error: ext2fs library version "
13188 "out of date!\n"));
13189 show_version_only++;
13190 }
13191
13192 retval = PRS(argc, argv, &ctx);
13193 if (retval) {
13194 bb_error_msg(_("while trying to initialize program"));
13195 exit(EXIT_ERROR);
13196 }
13197 reserve_stdio_fds();
13198
13199 if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13200 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13201 my_ver_date);
13202
13203 if (show_version_only) {
13204 fprintf(stderr, _("\tUsing %s, %s\n"),
13205 error_message(EXT2_ET_BASE), lib_ver_date);
13206 exit(EXIT_OK);
13207 }
13208
13209 check_mount(ctx);
13210
13211 if (!(ctx->options & E2F_OPT_PREEN) &&
13212 !(ctx->options & E2F_OPT_NO) &&
13213 !(ctx->options & E2F_OPT_YES)) {
13214 if (!ctx->interactive)
13215 bb_error_msg_and_die(_("need terminal for interactive repairs"));
13216 }
13217 ctx->superblock = ctx->use_superblock;
13218restart:
13219#ifdef CONFIG_TESTIO_DEBUG
13220 io_ptr = test_io_manager;
13221 test_io_backing_manager = unix_io_manager;
13222#else
13223 io_ptr = unix_io_manager;
13224#endif
13225 flags = 0;
13226 if ((ctx->options & E2F_OPT_READONLY) == 0)
13227 flags |= EXT2_FLAG_RW;
13228
13229 if (ctx->superblock && ctx->blocksize) {
13230 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13231 flags, ctx->superblock, ctx->blocksize,
13232 io_ptr, &fs);
13233 } else if (ctx->superblock) {
13234 int blocksize;
13235 for (blocksize = EXT2_MIN_BLOCK_SIZE;
13236 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13237 retval = ext2fs_open2(ctx->filesystem_name,
13238 ctx->io_options, flags,
13239 ctx->superblock, blocksize,
13240 io_ptr, &fs);
13241 if (!retval)
13242 break;
13243 }
13244 } else
13245 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13246 flags, 0, 0, io_ptr, &fs);
13247 if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13248 !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13249 ((retval == EXT2_ET_BAD_MAGIC) ||
13250 ((retval == 0) && ext2fs_check_desc(fs)))) {
13251 if (!fs || (fs->group_desc_count > 1)) {
13252 printf(_("%s trying backup blocks...\n"),
13253 retval ? _("Couldn't find ext2 superblock,") :
13254 _("Group descriptors look bad..."));
13255 get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13256 if (fs)
13257 ext2fs_close(fs);
13258 goto restart;
13259 }
13260 }
13261 if (retval) {
13262 bb_error_msg(_("while trying to open %s"),
13263 ctx->filesystem_name);
13264 if (retval == EXT2_ET_REV_TOO_HIGH) {
13265 printf(_("The filesystem revision is apparently "
13266 "too high for this version of e2fsck.\n"
13267 "(Or the filesystem superblock "
13268 "is corrupt)\n\n"));
13269 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13270 } else if (retval == EXT2_ET_SHORT_READ)
13271 printf(_("Could this be a zero-length partition?\n"));
13272 else if ((retval == EPERM) || (retval == EACCES))
13273 printf(_("You must have %s access to the "
13274 "filesystem or be root\n"),
13275 (ctx->options & E2F_OPT_READONLY) ?
13276 "r/o" : "r/w");
13277 else if (retval == ENXIO)
13278 printf(_("Possibly non-existent or swap device?\n"));
13279#ifdef EROFS
13280 else if (retval == EROFS)
13281 printf(_("Disk write-protected; use the -n option "
13282 "to do a read-only\n"
13283 "check of the device.\n"));
13284#endif
13285 else
13286 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13287 bb_error_msg_and_die(0);
13288 }
13289 ctx->fs = fs;
13290 fs->priv_data = ctx;
13291 sb = fs->super;
13292 if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13293 bb_error_msg(_("while trying to open %s"),
13294 ctx->filesystem_name);
13295 get_newer:
13296 bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13297 }
13298
13299 /*
13300 * Set the device name, which is used whenever we print error
13301 * or informational messages to the user.
13302 */
13303 if (ctx->device_name == 0 &&
13304 (sb->s_volume_name[0] != 0)) {
13305 ctx->device_name = string_copy(sb->s_volume_name,
13306 sizeof(sb->s_volume_name));
13307 }
13308 if (ctx->device_name == 0)
13309 ctx->device_name = ctx->filesystem_name;
13310
13311 /*
13312 * Make sure the ext3 superblock fields are consistent.
13313 */
13314 retval = e2fsck_check_ext3_journal(ctx);
13315 if (retval) {
13316 bb_error_msg(_("while checking ext3 journal for %s"),
13317 ctx->device_name);
13318 bb_error_msg_and_die(0);
13319 }
13320
13321 /*
13322 * Check to see if we need to do ext3-style recovery. If so,
13323 * do it, and then restart the fsck.
13324 */
13325 if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13326 if (ctx->options & E2F_OPT_READONLY) {
13327 printf(_("Warning: skipping journal recovery "
13328 "because doing a read-only filesystem "
13329 "check.\n"));
13330 io_channel_flush(ctx->fs->io);
13331 } else {
13332 if (ctx->flags & E2F_FLAG_RESTARTED) {
13333 /*
13334 * Whoops, we attempted to run the
13335 * journal twice. This should never
13336 * happen, unless the hardware or
13337 * device driver is being bogus.
13338 */
Denys Vlasenko6331cf02009-11-13 09:08:27 +010013339 bb_error_msg(_("can't set superblock flags on %s"), ctx->device_name);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013340 bb_error_msg_and_die(0);
13341 }
13342 retval = e2fsck_run_ext3_journal(ctx);
13343 if (retval) {
13344 bb_error_msg(_("while recovering ext3 journal of %s"),
13345 ctx->device_name);
13346 bb_error_msg_and_die(0);
13347 }
13348 ext2fs_close(ctx->fs);
13349 ctx->fs = 0;
13350 ctx->flags |= E2F_FLAG_RESTARTED;
13351 goto restart;
13352 }
13353 }
13354
13355 /*
13356 * Check for compatibility with the feature sets. We need to
13357 * be more stringent than ext2fs_open().
13358 */
13359 if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13360 (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13361 bb_error_msg("(%s)", ctx->device_name);
13362 goto get_newer;
13363 }
13364 if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13365 bb_error_msg("(%s)", ctx->device_name);
13366 goto get_newer;
13367 }
13368#ifdef ENABLE_COMPRESSION
13369 /* FIXME - do we support this at all? */
13370 if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
Denis Vlasenko54d10052008-12-24 03:11:43 +000013371 bb_error_msg(_("warning: compression support is experimental"));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013372#endif
13373#ifndef ENABLE_HTREE
13374 if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13375 bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13376 "but filesystem %s has HTREE directories."),
13377 ctx->device_name);
13378 goto get_newer;
13379 }
13380#endif
13381
13382 /*
13383 * If the user specified a specific superblock, presumably the
13384 * master superblock has been trashed. So we mark the
13385 * superblock as dirty, so it can be written out.
13386 */
13387 if (ctx->superblock &&
13388 !(ctx->options & E2F_OPT_READONLY))
13389 ext2fs_mark_super_dirty(fs);
13390
13391 /*
13392 * We only update the master superblock because (a) paranoia;
13393 * we don't want to corrupt the backup superblocks, and (b) we
13394 * don't need to update the mount count and last checked
13395 * fields in the backup superblock (the kernel doesn't
13396 * update the backup superblocks anyway).
13397 */
13398 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13399
13400 ehandler_init(fs->io);
13401
13402 if (ctx->superblock)
13403 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13404 ext2fs_mark_valid(fs);
13405 check_super_block(ctx);
13406 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13407 bb_error_msg_and_die(0);
13408 check_if_skip(ctx);
13409 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13410 bb_error_msg_and_die(0);
13411#ifdef ENABLE_SWAPFS
13412
13413#ifdef WORDS_BIGENDIAN
13414#define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13415#else
13416#define NATIVE_FLAG 0
13417#endif
13418
13419
13420 if (normalize_swapfs) {
13421 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13422 fprintf(stderr, _("%s: Filesystem byte order "
13423 "already normalized.\n"), ctx->device_name);
13424 bb_error_msg_and_die(0);
13425 }
13426 }
13427 if (swapfs) {
13428 swap_filesys(ctx);
13429 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13430 bb_error_msg_and_die(0);
13431 }
13432#endif
13433
13434 /*
13435 * Mark the system as valid, 'til proven otherwise
13436 */
13437 ext2fs_mark_valid(fs);
13438
13439 retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13440 if (retval) {
13441 bb_error_msg(_("while reading bad blocks inode"));
13442 preenhalt(ctx);
13443 printf(_("This doesn't bode well,"
13444 " but we'll try to go on...\n"));
13445 }
13446
13447 run_result = e2fsck_run(ctx);
13448 e2fsck_clear_progbar(ctx);
13449 if (run_result == E2F_FLAG_RESTART) {
13450 printf(_("Restarting e2fsck from the beginning...\n"));
13451 retval = e2fsck_reset_context(ctx);
13452 if (retval) {
13453 bb_error_msg(_("while resetting context"));
13454 bb_error_msg_and_die(0);
13455 }
13456 ext2fs_close(fs);
13457 goto restart;
13458 }
13459 if (run_result & E2F_FLAG_CANCEL) {
13460 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13461 ctx->device_name : ctx->filesystem_name);
13462 exit_value |= FSCK_CANCELED;
13463 }
13464 if (run_result & E2F_FLAG_ABORT)
13465 bb_error_msg_and_die(_("aborted"));
13466
13467 /* Cleanup */
13468 if (ext2fs_test_changed(fs)) {
13469 exit_value |= EXIT_NONDESTRUCT;
13470 if (!(ctx->options & E2F_OPT_PREEN))
13471 printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13472 ctx->device_name);
13473 if (ctx->mount_flags & EXT2_MF_ISROOT) {
13474 printf(_("%s: ***** REBOOT LINUX *****\n"),
13475 ctx->device_name);
13476 exit_value |= EXIT_DESTRUCT;
13477 }
13478 }
13479 if (!ext2fs_test_valid(fs)) {
13480 printf(_("\n%s: ********** WARNING: Filesystem still has "
13481 "errors **********\n\n"), ctx->device_name);
13482 exit_value |= EXIT_UNCORRECTED;
13483 exit_value &= ~EXIT_NONDESTRUCT;
13484 }
13485 if (exit_value & FSCK_CANCELED)
13486 exit_value &= ~EXIT_NONDESTRUCT;
13487 else {
13488 show_stats(ctx);
13489 if (!(ctx->options & E2F_OPT_READONLY)) {
13490 if (ext2fs_test_valid(fs)) {
13491 if (!(sb->s_state & EXT2_VALID_FS))
13492 exit_value |= EXIT_NONDESTRUCT;
13493 sb->s_state = EXT2_VALID_FS;
13494 } else
13495 sb->s_state &= ~EXT2_VALID_FS;
13496 sb->s_mnt_count = 0;
13497 sb->s_lastcheck = time(NULL);
13498 ext2fs_mark_super_dirty(fs);
13499 }
13500 }
13501
13502 e2fsck_write_bitmaps(ctx);
13503
13504 ext2fs_close(fs);
13505 ctx->fs = NULL;
13506 free(ctx->filesystem_name);
13507 free(ctx->journal_name);
13508 e2fsck_free_context(ctx);
13509
13510 return exit_value;
13511}