Changes for kernel and Busybox
[tomato.git] / release / src / router / busybox / e2fsprogs / e2fsck.c
blobfd682322a690db6d273c6cd367ecad5d56f0de4b
1 /* vi: set sw=4 ts=4: */
2 /*
3 * e2fsck
5 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
6 * Copyright (C) 2006 Garrett Kajmowicz
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.
21 * linux/fs/recovery and linux/fs/revoke
22 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
24 * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
26 * Journal recovery routines for the generic filesystem journaling code;
27 * part of the ext2fs journaling system.
29 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
32 //usage:#define e2fsck_trivial_usage
33 //usage: "[-panyrcdfvstDFSV] [-b superblock] [-B blocksize] "
34 //usage: "[-I inode_buffer_blocks] [-P process_inode_size] "
35 //usage: "[-l|-L bad_blocks_file] [-C fd] [-j external_journal] "
36 //usage: "[-E extended-options] device"
37 //usage:#define e2fsck_full_usage "\n\n"
38 //usage: "Check ext2/ext3 file system\n"
39 //usage: "\n -p Automatic repair (no questions)"
40 //usage: "\n -n Make no changes to the filesystem"
41 //usage: "\n -y Assume 'yes' to all questions"
42 //usage: "\n -c Check for bad blocks and add them to the badblock list"
43 //usage: "\n -f Force checking even if filesystem is marked clean"
44 //usage: "\n -v Verbose"
45 //usage: "\n -b superblock Use alternative superblock"
46 //usage: "\n -B blocksize Force blocksize when looking for superblock"
47 //usage: "\n -j journal Set location of the external journal"
48 //usage: "\n -l file Add to badblocks list"
49 //usage: "\n -L file Set badblocks list"
50 //usage:
51 //applet:IF_E2FSCK(APPLET(e2fsck, BB_DIR_SBIN, BB_SUID_DROP))
52 //applet:IF_E2FSCK(APPLET_ODDNAME(fsck.ext2, e2fsck, BB_DIR_SBIN, BB_SUID_DROP, e2fsck))
53 //applet:IF_E2FSCK(APPLET_ODDNAME(fsck.ext3, e2fsck, BB_DIR_SBIN, BB_SUID_DROP, e2fsck))
56 #include "e2fsck.h" /*Put all of our defines here to clean things up*/
58 #define _(x) x
59 #define N_(x) x
62 * Procedure declarations
65 static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
67 /* pass1.c */
68 static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int fl_bool);
70 /* pass2.c */
71 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
72 ext2_ino_t ino, char *buf);
74 /* pass3.c */
75 static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
76 static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
77 int num, int gauranteed_size);
78 static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
79 static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
80 int adj);
82 /* rehash.c */
83 static void e2fsck_rehash_directories(e2fsck_t ctx);
85 /* util.c */
86 static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
87 const char *description);
88 static int ask(e2fsck_t ctx, const char * string, int def);
89 static void e2fsck_read_bitmaps(e2fsck_t ctx);
90 static void preenhalt(e2fsck_t ctx);
91 static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
92 struct ext2_inode * inode, const char * proc);
93 static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
94 struct ext2_inode * inode, const char * proc);
95 static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
96 const char *name, io_manager manager);
98 /* unix.c */
99 static void e2fsck_clear_progbar(e2fsck_t ctx);
100 static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
101 float percent, unsigned int dpynum);
105 * problem.h --- e2fsck problem error codes
108 typedef __u32 problem_t;
110 struct problem_context {
111 errcode_t errcode;
112 ext2_ino_t ino, ino2, dir;
113 struct ext2_inode *inode;
114 struct ext2_dir_entry *dirent;
115 blk_t blk, blk2;
116 e2_blkcnt_t blkcount;
117 int group;
118 __u64 num;
119 const char *str;
124 * Function declarations
126 static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
127 static int end_problem_latch(e2fsck_t ctx, int mask);
128 static int set_latch_flags(int mask, int setflags, int clearflags);
129 static void clear_problem_context(struct problem_context *ctx);
132 * Dictionary Abstract Data Type
133 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
135 * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
136 * kazlib_1_20
139 #ifndef DICT_H
140 #define DICT_H
143 * Blurb for inclusion into C++ translation units
146 typedef unsigned long dictcount_t;
147 #define DICTCOUNT_T_MAX ULONG_MAX
150 * The dictionary is implemented as a red-black tree
153 typedef enum { dnode_red, dnode_black } dnode_color_t;
155 typedef struct dnode_t {
156 struct dnode_t *dict_left;
157 struct dnode_t *dict_right;
158 struct dnode_t *dict_parent;
159 dnode_color_t dict_color;
160 const void *dict_key;
161 void *dict_data;
162 } dnode_t;
164 typedef int (*dict_comp_t)(const void *, const void *);
165 typedef void (*dnode_free_t)(dnode_t *);
167 typedef struct dict_t {
168 dnode_t dict_nilnode;
169 dictcount_t dict_nodecount;
170 dictcount_t dict_maxcount;
171 dict_comp_t dict_compare;
172 dnode_free_t dict_freenode;
173 int dict_dupes;
174 } dict_t;
176 typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
178 typedef struct dict_load_t {
179 dict_t *dict_dictptr;
180 dnode_t dict_nilnode;
181 } dict_load_t;
183 #define dict_count(D) ((D)->dict_nodecount)
184 #define dnode_get(N) ((N)->dict_data)
185 #define dnode_getkey(N) ((N)->dict_key)
187 #endif
190 * Compatibility header file for e2fsck which should be included
191 * instead of linux/jfs.h
193 * Copyright (C) 2000 Stephen C. Tweedie
197 * Pull in the definition of the e2fsck context structure
200 struct buffer_head {
201 char b_data[8192];
202 e2fsck_t b_ctx;
203 io_channel b_io;
204 int b_size;
205 blk_t b_blocknr;
206 int b_dirty;
207 int b_uptodate;
208 int b_err;
212 #define K_DEV_FS 1
213 #define K_DEV_JOURNAL 2
215 #define lock_buffer(bh) do {} while (0)
216 #define unlock_buffer(bh) do {} while (0)
217 #define buffer_req(bh) 1
218 #define do_readahead(journal, start) do {} while (0)
220 static e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
222 typedef struct {
223 int object_length;
224 } kmem_cache_t;
226 #define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
229 * We use the standard libext2fs portability tricks for inline
230 * functions.
233 static kmem_cache_t * do_cache_create(int len)
235 kmem_cache_t *new_cache;
237 new_cache = xmalloc(sizeof(*new_cache));
238 new_cache->object_length = len;
239 return new_cache;
242 static void do_cache_destroy(kmem_cache_t *cache)
244 free(cache);
249 * Dictionary Abstract Data Type
254 * These macros provide short convenient names for structure members,
255 * which are embellished with dict_ prefixes so that they are
256 * properly confined to the documented namespace. It's legal for a
257 * program which uses dict to define, for instance, a macro called ``parent''.
258 * Such a macro would interfere with the dnode_t struct definition.
259 * In general, highly portable and reusable C modules which expose their
260 * structures need to confine structure member names to well-defined spaces.
261 * The resulting identifiers aren't necessarily convenient to use, nor
262 * readable, in the implementation, however!
265 #define left dict_left
266 #define right dict_right
267 #define parent dict_parent
268 #define color dict_color
269 #define key dict_key
270 #define data dict_data
272 #define nilnode dict_nilnode
273 #define maxcount dict_maxcount
274 #define compare dict_compare
275 #define dupes dict_dupes
277 #define dict_root(D) ((D)->nilnode.left)
278 #define dict_nil(D) (&(D)->nilnode)
280 static void dnode_free(dnode_t *node);
283 * Perform a ``left rotation'' adjustment on the tree. The given node P and
284 * its right child C are rearranged so that the P instead becomes the left
285 * child of C. The left subtree of C is inherited as the new right subtree
286 * for P. The ordering of the keys within the tree is thus preserved.
289 static void rotate_left(dnode_t *upper)
291 dnode_t *lower, *lowleft, *upparent;
293 lower = upper->right;
294 upper->right = lowleft = lower->left;
295 lowleft->parent = upper;
297 lower->parent = upparent = upper->parent;
299 /* don't need to check for root node here because root->parent is
300 the sentinel nil node, and root->parent->left points back to root */
302 if (upper == upparent->left) {
303 upparent->left = lower;
304 } else {
305 assert (upper == upparent->right);
306 upparent->right = lower;
309 lower->left = upper;
310 upper->parent = lower;
314 * This operation is the ``mirror'' image of rotate_left. It is
315 * the same procedure, but with left and right interchanged.
318 static void rotate_right(dnode_t *upper)
320 dnode_t *lower, *lowright, *upparent;
322 lower = upper->left;
323 upper->left = lowright = lower->right;
324 lowright->parent = upper;
326 lower->parent = upparent = upper->parent;
328 if (upper == upparent->right) {
329 upparent->right = lower;
330 } else {
331 assert (upper == upparent->left);
332 upparent->left = lower;
335 lower->right = upper;
336 upper->parent = lower;
340 * Do a postorder traversal of the tree rooted at the specified
341 * node and free everything under it. Used by dict_free().
344 static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
346 if (node == nil)
347 return;
348 free_nodes(dict, node->left, nil);
349 free_nodes(dict, node->right, nil);
350 dict->dict_freenode(node);
354 * Verify that the tree contains the given node. This is done by
355 * traversing all of the nodes and comparing their pointers to the
356 * given pointer. Returns 1 if the node is found, otherwise
357 * returns zero. It is intended for debugging purposes.
360 static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
362 if (root != nil) {
363 return root == node
364 || verify_dict_has_node(nil, root->left, node)
365 || verify_dict_has_node(nil, root->right, node);
367 return 0;
372 * Select a different set of node allocator routines.
375 static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
377 assert(dict_count(dict) == 0);
378 dict->dict_freenode = fr;
382 * Free all the nodes in the dictionary by using the dictionary's
383 * installed free routine. The dictionary is emptied.
386 static void dict_free_nodes(dict_t *dict)
388 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
389 free_nodes(dict, root, nil);
390 dict->dict_nodecount = 0;
391 dict->nilnode.left = &dict->nilnode;
392 dict->nilnode.right = &dict->nilnode;
396 * Initialize a user-supplied dictionary object.
399 static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
401 dict->compare = comp;
402 dict->dict_freenode = dnode_free;
403 dict->dict_nodecount = 0;
404 dict->maxcount = maxcount;
405 dict->nilnode.left = &dict->nilnode;
406 dict->nilnode.right = &dict->nilnode;
407 dict->nilnode.parent = &dict->nilnode;
408 dict->nilnode.color = dnode_black;
409 dict->dupes = 0;
410 return dict;
414 * Locate a node in the dictionary having the given key.
415 * If the node is not found, a null a pointer is returned (rather than
416 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
417 * located node is returned.
420 static dnode_t *dict_lookup(dict_t *dict, const void *key)
422 dnode_t *root = dict_root(dict);
423 dnode_t *nil = dict_nil(dict);
424 dnode_t *saved;
425 int result;
427 /* simple binary search adapted for trees that contain duplicate keys */
429 while (root != nil) {
430 result = dict->compare(key, root->key);
431 if (result < 0)
432 root = root->left;
433 else if (result > 0)
434 root = root->right;
435 else {
436 if (!dict->dupes) { /* no duplicates, return match */
437 return root;
438 } else { /* could be dupes, find leftmost one */
439 do {
440 saved = root;
441 root = root->left;
442 while (root != nil && dict->compare(key, root->key))
443 root = root->right;
444 } while (root != nil);
445 return saved;
450 return NULL;
454 * Insert a node into the dictionary. The node should have been
455 * initialized with a data field. All other fields are ignored.
456 * The behavior is undefined if the user attempts to insert into
457 * a dictionary that is already full (for which the dict_isfull()
458 * function returns true).
461 static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
463 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
464 dnode_t *parent = nil, *uncle, *grandpa;
465 int result = -1;
467 node->key = key;
469 /* basic binary tree insert */
471 while (where != nil) {
472 parent = where;
473 result = dict->compare(key, where->key);
474 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
475 assert(dict->dupes || result != 0);
476 if (result < 0)
477 where = where->left;
478 else
479 where = where->right;
482 assert(where == nil);
484 if (result < 0)
485 parent->left = node;
486 else
487 parent->right = node;
489 node->parent = parent;
490 node->left = nil;
491 node->right = nil;
493 dict->dict_nodecount++;
495 /* red black adjustments */
497 node->color = dnode_red;
499 while (parent->color == dnode_red) {
500 grandpa = parent->parent;
501 if (parent == grandpa->left) {
502 uncle = grandpa->right;
503 if (uncle->color == dnode_red) { /* red parent, red uncle */
504 parent->color = dnode_black;
505 uncle->color = dnode_black;
506 grandpa->color = dnode_red;
507 node = grandpa;
508 parent = grandpa->parent;
509 } else { /* red parent, black uncle */
510 if (node == parent->right) {
511 rotate_left(parent);
512 parent = node;
513 assert (grandpa == parent->parent);
514 /* rotation between parent and child preserves grandpa */
516 parent->color = dnode_black;
517 grandpa->color = dnode_red;
518 rotate_right(grandpa);
519 break;
521 } else { /* symmetric cases: parent == parent->parent->right */
522 uncle = grandpa->left;
523 if (uncle->color == dnode_red) {
524 parent->color = dnode_black;
525 uncle->color = dnode_black;
526 grandpa->color = dnode_red;
527 node = grandpa;
528 parent = grandpa->parent;
529 } else {
530 if (node == parent->left) {
531 rotate_right(parent);
532 parent = node;
533 assert (grandpa == parent->parent);
535 parent->color = dnode_black;
536 grandpa->color = dnode_red;
537 rotate_left(grandpa);
538 break;
543 dict_root(dict)->color = dnode_black;
547 * Allocate a node using the dictionary's allocator routine, give it
548 * the data item.
551 static dnode_t *dnode_init(dnode_t *dnode, void *data)
553 dnode->data = data;
554 dnode->parent = NULL;
555 dnode->left = NULL;
556 dnode->right = NULL;
557 return dnode;
560 static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
562 dnode_t *node = xmalloc(sizeof(dnode_t));
564 dnode_init(node, data);
565 dict_insert(dict, node, key);
566 return 1;
570 * Return the node with the lowest (leftmost) key. If the dictionary is empty
571 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
574 static dnode_t *dict_first(dict_t *dict)
576 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
578 if (root != nil)
579 while ((left = root->left) != nil)
580 root = left;
582 return (root == nil) ? NULL : root;
586 * Return the given node's successor node---the node which has the
587 * next key in the left to right ordering. If the node has
588 * no successor, a null pointer is returned rather than a pointer to
589 * the nil node.
592 static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
594 dnode_t *nil = dict_nil(dict), *parent, *left;
596 if (curr->right != nil) {
597 curr = curr->right;
598 while ((left = curr->left) != nil)
599 curr = left;
600 return curr;
603 parent = curr->parent;
605 while (parent != nil && curr == parent->right) {
606 curr = parent;
607 parent = curr->parent;
610 return (parent == nil) ? NULL : parent;
614 static void dnode_free(dnode_t *node)
616 free(node);
620 #undef left
621 #undef right
622 #undef parent
623 #undef color
624 #undef key
625 #undef data
627 #undef nilnode
628 #undef maxcount
629 #undef compare
630 #undef dupes
634 * dirinfo.c --- maintains the directory information table for e2fsck.
638 * This subroutine is called during pass1 to create a directory info
639 * entry. During pass1, the passed-in parent is 0; it will get filled
640 * in during pass2.
642 static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
644 struct dir_info *dir;
645 int i, j;
646 ext2_ino_t num_dirs;
647 errcode_t retval;
648 unsigned long old_size;
650 if (!ctx->dir_info) {
651 ctx->dir_info_count = 0;
652 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
653 if (retval)
654 num_dirs = 1024; /* Guess */
655 ctx->dir_info_size = num_dirs + 10;
656 ctx->dir_info = (struct dir_info *)
657 e2fsck_allocate_memory(ctx, ctx->dir_info_size
658 * sizeof (struct dir_info),
659 "directory map");
662 if (ctx->dir_info_count >= ctx->dir_info_size) {
663 old_size = ctx->dir_info_size * sizeof(struct dir_info);
664 ctx->dir_info_size += 10;
665 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
666 sizeof(struct dir_info),
667 &ctx->dir_info);
668 if (retval) {
669 ctx->dir_info_size -= 10;
670 return;
675 * Normally, add_dir_info is called with each inode in
676 * sequential order; but once in a while (like when pass 3
677 * needs to recreate the root directory or lost+found
678 * directory) it is called out of order. In those cases, we
679 * need to move the dir_info entries down to make room, since
680 * the dir_info array needs to be sorted by inode number for
681 * get_dir_info()'s sake.
683 if (ctx->dir_info_count &&
684 ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
685 for (i = ctx->dir_info_count-1; i > 0; i--)
686 if (ctx->dir_info[i-1].ino < ino)
687 break;
688 dir = &ctx->dir_info[i];
689 if (dir->ino != ino)
690 for (j = ctx->dir_info_count++; j > i; j--)
691 ctx->dir_info[j] = ctx->dir_info[j-1];
692 } else
693 dir = &ctx->dir_info[ctx->dir_info_count++];
695 dir->ino = ino;
696 dir->dotdot = parent;
697 dir->parent = parent;
701 * get_dir_info() --- given an inode number, try to find the directory
702 * information entry for it.
704 static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
706 int low, high, mid;
708 low = 0;
709 high = ctx->dir_info_count-1;
710 if (!ctx->dir_info)
711 return 0;
712 if (ino == ctx->dir_info[low].ino)
713 return &ctx->dir_info[low];
714 if (ino == ctx->dir_info[high].ino)
715 return &ctx->dir_info[high];
717 while (low < high) {
718 mid = (low+high)/2;
719 if (mid == low || mid == high)
720 break;
721 if (ino == ctx->dir_info[mid].ino)
722 return &ctx->dir_info[mid];
723 if (ino < ctx->dir_info[mid].ino)
724 high = mid;
725 else
726 low = mid;
728 return 0;
732 * Free the dir_info structure when it isn't needed any more.
734 static void e2fsck_free_dir_info(e2fsck_t ctx)
736 ext2fs_free_mem(&ctx->dir_info);
737 ctx->dir_info_size = 0;
738 ctx->dir_info_count = 0;
742 * Return the count of number of directories in the dir_info structure
744 static int e2fsck_get_num_dirinfo(e2fsck_t ctx)
746 return ctx->dir_info_count;
750 * A simple interator function
752 static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
754 if (*control >= ctx->dir_info_count)
755 return 0;
757 return ctx->dir_info + (*control)++;
761 * dirinfo.c --- maintains the directory information table for e2fsck.
765 #ifdef ENABLE_HTREE
768 * This subroutine is called during pass1 to create a directory info
769 * entry. During pass1, the passed-in parent is 0; it will get filled
770 * in during pass2.
772 static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
774 struct dx_dir_info *dir;
775 int i, j;
776 errcode_t retval;
777 unsigned long old_size;
779 if (!ctx->dx_dir_info) {
780 ctx->dx_dir_info_count = 0;
781 ctx->dx_dir_info_size = 100; /* Guess */
782 ctx->dx_dir_info = (struct dx_dir_info *)
783 e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
784 * sizeof (struct dx_dir_info),
785 "directory map");
788 if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
789 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
790 ctx->dx_dir_info_size += 10;
791 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
792 sizeof(struct dx_dir_info),
793 &ctx->dx_dir_info);
794 if (retval) {
795 ctx->dx_dir_info_size -= 10;
796 return;
801 * Normally, add_dx_dir_info is called with each inode in
802 * sequential order; but once in a while (like when pass 3
803 * needs to recreate the root directory or lost+found
804 * directory) it is called out of order. In those cases, we
805 * need to move the dx_dir_info entries down to make room, since
806 * the dx_dir_info array needs to be sorted by inode number for
807 * get_dx_dir_info()'s sake.
809 if (ctx->dx_dir_info_count &&
810 ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
811 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
812 if (ctx->dx_dir_info[i-1].ino < ino)
813 break;
814 dir = &ctx->dx_dir_info[i];
815 if (dir->ino != ino)
816 for (j = ctx->dx_dir_info_count++; j > i; j--)
817 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
818 } else
819 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
821 dir->ino = ino;
822 dir->numblocks = num_blocks;
823 dir->hashversion = 0;
824 dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
825 * sizeof (struct dx_dirblock_info),
826 "dx_block info array");
830 * get_dx_dir_info() --- given an inode number, try to find the directory
831 * information entry for it.
833 static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
835 int low, high, mid;
837 low = 0;
838 high = ctx->dx_dir_info_count-1;
839 if (!ctx->dx_dir_info)
840 return 0;
841 if (ino == ctx->dx_dir_info[low].ino)
842 return &ctx->dx_dir_info[low];
843 if (ino == ctx->dx_dir_info[high].ino)
844 return &ctx->dx_dir_info[high];
846 while (low < high) {
847 mid = (low+high)/2;
848 if (mid == low || mid == high)
849 break;
850 if (ino == ctx->dx_dir_info[mid].ino)
851 return &ctx->dx_dir_info[mid];
852 if (ino < ctx->dx_dir_info[mid].ino)
853 high = mid;
854 else
855 low = mid;
857 return 0;
861 * Free the dx_dir_info structure when it isn't needed any more.
863 static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
865 int i;
866 struct dx_dir_info *dir;
868 if (ctx->dx_dir_info) {
869 dir = ctx->dx_dir_info;
870 for (i=0; i < ctx->dx_dir_info_count; i++) {
871 ext2fs_free_mem(&dir->dx_block);
873 ext2fs_free_mem(&ctx->dx_dir_info);
875 ctx->dx_dir_info_size = 0;
876 ctx->dx_dir_info_count = 0;
880 * A simple interator function
882 static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
884 if (*control >= ctx->dx_dir_info_count)
885 return 0;
887 return ctx->dx_dir_info + (*control)++;
890 #endif /* ENABLE_HTREE */
892 * e2fsck.c - a consistency checker for the new extended file system.
897 * This function allocates an e2fsck context
899 static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
901 e2fsck_t context;
902 errcode_t retval;
904 retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
905 if (retval)
906 return retval;
908 memset(context, 0, sizeof(struct e2fsck_struct));
910 context->process_inode_size = 256;
911 context->ext_attr_ver = 2;
913 *ret = context;
914 return 0;
917 struct ea_refcount_el {
918 blk_t ea_blk;
919 int ea_count;
922 struct ea_refcount {
923 blk_t count;
924 blk_t size;
925 blk_t cursor;
926 struct ea_refcount_el *list;
929 static void ea_refcount_free(ext2_refcount_t refcount)
931 if (!refcount)
932 return;
934 ext2fs_free_mem(&refcount->list);
935 ext2fs_free_mem(&refcount);
939 * This function resets an e2fsck context; it is called when e2fsck
940 * needs to be restarted.
942 static errcode_t e2fsck_reset_context(e2fsck_t ctx)
944 ctx->flags = 0;
945 ctx->lost_and_found = 0;
946 ctx->bad_lost_and_found = 0;
947 ext2fs_free_inode_bitmap(ctx->inode_used_map);
948 ctx->inode_used_map = 0;
949 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
950 ctx->inode_dir_map = 0;
951 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
952 ctx->inode_reg_map = 0;
953 ext2fs_free_block_bitmap(ctx->block_found_map);
954 ctx->block_found_map = 0;
955 ext2fs_free_icount(ctx->inode_link_info);
956 ctx->inode_link_info = 0;
957 if (ctx->journal_io) {
958 if (ctx->fs && ctx->fs->io != ctx->journal_io)
959 io_channel_close(ctx->journal_io);
960 ctx->journal_io = 0;
962 if (ctx->fs) {
963 ext2fs_free_dblist(ctx->fs->dblist);
964 ctx->fs->dblist = 0;
966 e2fsck_free_dir_info(ctx);
967 #ifdef ENABLE_HTREE
968 e2fsck_free_dx_dir_info(ctx);
969 #endif
970 ea_refcount_free(ctx->refcount);
971 ctx->refcount = 0;
972 ea_refcount_free(ctx->refcount_extra);
973 ctx->refcount_extra = 0;
974 ext2fs_free_block_bitmap(ctx->block_dup_map);
975 ctx->block_dup_map = 0;
976 ext2fs_free_block_bitmap(ctx->block_ea_map);
977 ctx->block_ea_map = 0;
978 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
979 ctx->inode_bad_map = 0;
980 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
981 ctx->inode_imagic_map = 0;
982 ext2fs_u32_list_free(ctx->dirs_to_hash);
983 ctx->dirs_to_hash = 0;
986 * Clear the array of invalid meta-data flags
988 ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
989 ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
990 ext2fs_free_mem(&ctx->invalid_inode_table_flag);
992 /* Clear statistic counters */
993 ctx->fs_directory_count = 0;
994 ctx->fs_regular_count = 0;
995 ctx->fs_blockdev_count = 0;
996 ctx->fs_chardev_count = 0;
997 ctx->fs_links_count = 0;
998 ctx->fs_symlinks_count = 0;
999 ctx->fs_fast_symlinks_count = 0;
1000 ctx->fs_fifo_count = 0;
1001 ctx->fs_total_count = 0;
1002 ctx->fs_sockets_count = 0;
1003 ctx->fs_ind_count = 0;
1004 ctx->fs_dind_count = 0;
1005 ctx->fs_tind_count = 0;
1006 ctx->fs_fragmented = 0;
1007 ctx->large_files = 0;
1009 /* Reset the superblock to the user's requested value */
1010 ctx->superblock = ctx->use_superblock;
1012 return 0;
1015 static void e2fsck_free_context(e2fsck_t ctx)
1017 if (!ctx)
1018 return;
1020 e2fsck_reset_context(ctx);
1022 ext2fs_free_mem(&ctx);
1026 * ea_refcount.c
1030 * The strategy we use for keeping track of EA refcounts is as
1031 * follows. We keep a sorted array of first EA blocks and its
1032 * reference counts. Once the refcount has dropped to zero, it is
1033 * removed from the array to save memory space. Once the EA block is
1034 * checked, its bit is set in the block_ea_map bitmap.
1038 static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
1040 ext2_refcount_t refcount;
1041 errcode_t retval;
1042 size_t bytes;
1044 retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
1045 if (retval)
1046 return retval;
1047 memset(refcount, 0, sizeof(struct ea_refcount));
1049 if (!size)
1050 size = 500;
1051 refcount->size = size;
1052 bytes = (size_t) (size * sizeof(struct ea_refcount_el));
1053 #ifdef DEBUG
1054 printf("Refcount allocated %d entries, %d bytes.\n",
1055 refcount->size, bytes);
1056 #endif
1057 retval = ext2fs_get_mem(bytes, &refcount->list);
1058 if (retval)
1059 goto errout;
1060 memset(refcount->list, 0, bytes);
1062 refcount->count = 0;
1063 refcount->cursor = 0;
1065 *ret = refcount;
1066 return 0;
1068 errout:
1069 ea_refcount_free(refcount);
1070 return retval;
1074 * collapse_refcount() --- go through the refcount array, and get rid
1075 * of any count == zero entries
1077 static void refcount_collapse(ext2_refcount_t refcount)
1079 unsigned int i, j;
1080 struct ea_refcount_el *list;
1082 list = refcount->list;
1083 for (i = 0, j = 0; i < refcount->count; i++) {
1084 if (list[i].ea_count) {
1085 if (i != j)
1086 list[j] = list[i];
1087 j++;
1090 #if defined(DEBUG) || defined(TEST_PROGRAM)
1091 printf("Refcount_collapse: size was %d, now %d\n",
1092 refcount->count, j);
1093 #endif
1094 refcount->count = j;
1099 * insert_refcount_el() --- Insert a new entry into the sorted list at a
1100 * specified position.
1102 static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
1103 blk_t blk, int pos)
1105 struct ea_refcount_el *el;
1106 errcode_t retval;
1107 blk_t new_size = 0;
1108 int num;
1110 if (refcount->count >= refcount->size) {
1111 new_size = refcount->size + 100;
1112 #ifdef DEBUG
1113 printf("Reallocating refcount %d entries...\n", new_size);
1114 #endif
1115 retval = ext2fs_resize_mem((size_t) refcount->size *
1116 sizeof(struct ea_refcount_el),
1117 (size_t) new_size *
1118 sizeof(struct ea_refcount_el),
1119 &refcount->list);
1120 if (retval)
1121 return 0;
1122 refcount->size = new_size;
1124 num = (int) refcount->count - pos;
1125 if (num < 0)
1126 return 0; /* should never happen */
1127 if (num) {
1128 memmove(&refcount->list[pos+1], &refcount->list[pos],
1129 sizeof(struct ea_refcount_el) * num);
1131 refcount->count++;
1132 el = &refcount->list[pos];
1133 el->ea_count = 0;
1134 el->ea_blk = blk;
1135 return el;
1140 * get_refcount_el() --- given an block number, try to find refcount
1141 * information in the sorted list. If the create flag is set,
1142 * and we can't find an entry, create one in the sorted list.
1144 static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
1145 blk_t blk, int create)
1147 float range;
1148 int low, high, mid;
1149 blk_t lowval, highval;
1151 if (!refcount || !refcount->list)
1152 return 0;
1153 retry:
1154 low = 0;
1155 high = (int) refcount->count-1;
1156 if (create && ((refcount->count == 0) ||
1157 (blk > refcount->list[high].ea_blk))) {
1158 if (refcount->count >= refcount->size)
1159 refcount_collapse(refcount);
1161 return insert_refcount_el(refcount, blk,
1162 (unsigned) refcount->count);
1164 if (refcount->count == 0)
1165 return 0;
1167 if (refcount->cursor >= refcount->count)
1168 refcount->cursor = 0;
1169 if (blk == refcount->list[refcount->cursor].ea_blk)
1170 return &refcount->list[refcount->cursor++];
1171 #ifdef DEBUG
1172 printf("Non-cursor get_refcount_el: %u\n", blk);
1173 #endif
1174 while (low <= high) {
1175 if (low == high)
1176 mid = low;
1177 else {
1178 /* Interpolate for efficiency */
1179 lowval = refcount->list[low].ea_blk;
1180 highval = refcount->list[high].ea_blk;
1182 if (blk < lowval)
1183 range = 0;
1184 else if (blk > highval)
1185 range = 1;
1186 else
1187 range = ((float) (blk - lowval)) /
1188 (highval - lowval);
1189 mid = low + ((int) (range * (high-low)));
1192 if (blk == refcount->list[mid].ea_blk) {
1193 refcount->cursor = mid+1;
1194 return &refcount->list[mid];
1196 if (blk < refcount->list[mid].ea_blk)
1197 high = mid-1;
1198 else
1199 low = mid+1;
1202 * If we need to create a new entry, it should be right at
1203 * low (where high will be left at low-1).
1205 if (create) {
1206 if (refcount->count >= refcount->size) {
1207 refcount_collapse(refcount);
1208 if (refcount->count < refcount->size)
1209 goto retry;
1211 return insert_refcount_el(refcount, blk, low);
1213 return 0;
1216 static errcode_t
1217 ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
1219 struct ea_refcount_el *el;
1221 el = get_refcount_el(refcount, blk, 1);
1222 if (!el)
1223 return EXT2_ET_NO_MEMORY;
1224 el->ea_count++;
1226 if (ret)
1227 *ret = el->ea_count;
1228 return 0;
1231 static errcode_t
1232 ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
1234 struct ea_refcount_el *el;
1236 el = get_refcount_el(refcount, blk, 0);
1237 if (!el || el->ea_count == 0)
1238 return EXT2_ET_INVALID_ARGUMENT;
1240 el->ea_count--;
1242 if (ret)
1243 *ret = el->ea_count;
1244 return 0;
1247 static errcode_t
1248 ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
1250 struct ea_refcount_el *el;
1253 * Get the refcount element
1255 el = get_refcount_el(refcount, blk, count ? 1 : 0);
1256 if (!el)
1257 return count ? EXT2_ET_NO_MEMORY : 0;
1258 el->ea_count = count;
1259 return 0;
1262 static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
1264 refcount->cursor = 0;
1268 static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
1270 struct ea_refcount_el *list;
1272 while (1) {
1273 if (refcount->cursor >= refcount->count)
1274 return 0;
1275 list = refcount->list;
1276 if (list[refcount->cursor].ea_count) {
1277 if (ret)
1278 *ret = list[refcount->cursor].ea_count;
1279 return list[refcount->cursor++].ea_blk;
1281 refcount->cursor++;
1287 * ehandler.c --- handle bad block errors which come up during the
1288 * course of an e2fsck session.
1292 static const char *operation;
1294 static errcode_t
1295 e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
1296 void *data, size_t size FSCK_ATTR((unused)),
1297 int actual FSCK_ATTR((unused)), errcode_t error)
1299 int i;
1300 char *p;
1301 ext2_filsys fs = (ext2_filsys) channel->app_data;
1302 e2fsck_t ctx;
1304 ctx = (e2fsck_t) fs->priv_data;
1307 * If more than one block was read, try reading each block
1308 * separately. We could use the actual bytes read to figure
1309 * out where to start, but we don't bother.
1311 if (count > 1) {
1312 p = (char *) data;
1313 for (i=0; i < count; i++, p += channel->block_size, block++) {
1314 error = io_channel_read_blk(channel, block,
1315 1, p);
1316 if (error)
1317 return error;
1319 return 0;
1321 if (operation)
1322 printf(_("Error reading block %lu (%s) while %s. "), block,
1323 error_message(error), operation);
1324 else
1325 printf(_("Error reading block %lu (%s). "), block,
1326 error_message(error));
1327 preenhalt(ctx);
1328 if (ask(ctx, _("Ignore error"), 1)) {
1329 if (ask(ctx, _("Force rewrite"), 1))
1330 io_channel_write_blk(channel, block, 1, data);
1331 return 0;
1334 return error;
1337 static errcode_t
1338 e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
1339 const void *data, size_t size FSCK_ATTR((unused)),
1340 int actual FSCK_ATTR((unused)), errcode_t error)
1342 int i;
1343 const char *p;
1344 ext2_filsys fs = (ext2_filsys) channel->app_data;
1345 e2fsck_t ctx;
1347 ctx = (e2fsck_t) fs->priv_data;
1350 * If more than one block was written, try writing each block
1351 * separately. We could use the actual bytes read to figure
1352 * out where to start, but we don't bother.
1354 if (count > 1) {
1355 p = (const char *) data;
1356 for (i=0; i < count; i++, p += channel->block_size, block++) {
1357 error = io_channel_write_blk(channel, block,
1358 1, p);
1359 if (error)
1360 return error;
1362 return 0;
1365 if (operation)
1366 printf(_("Error writing block %lu (%s) while %s. "), block,
1367 error_message(error), operation);
1368 else
1369 printf(_("Error writing block %lu (%s). "), block,
1370 error_message(error));
1371 preenhalt(ctx);
1372 if (ask(ctx, _("Ignore error"), 1))
1373 return 0;
1375 return error;
1378 static const char *ehandler_operation(const char *op)
1380 const char *ret = operation;
1382 operation = op;
1383 return ret;
1386 static void ehandler_init(io_channel channel)
1388 channel->read_error = e2fsck_handle_read_error;
1389 channel->write_error = e2fsck_handle_write_error;
1393 * journal.c --- code for handling the "ext3" journal
1395 * Copyright (C) 2000 Andreas Dilger
1396 * Copyright (C) 2000 Theodore Ts'o
1398 * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
1399 * Copyright (C) 1999 Red Hat Software
1401 * This file may be redistributed under the terms of the
1402 * GNU General Public License version 2 or at your discretion
1403 * any later version.
1407 * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
1408 * This creates a larger static binary, and a smaller binary using
1409 * shared libraries. It's also probably slightly less CPU-efficient,
1410 * which is why it's not on by default. But, it's a good way of
1411 * testing the functions in inode_io.c and fileio.c.
1413 #undef USE_INODE_IO
1415 /* Kernel compatibility functions for handling the journal. These allow us
1416 * to use the recovery.c file virtually unchanged from the kernel, so we
1417 * don't have to do much to keep kernel and user recovery in sync.
1419 static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
1421 #ifdef USE_INODE_IO
1422 *phys = block;
1423 return 0;
1424 #else
1425 struct inode *inode = journal->j_inode;
1426 errcode_t retval;
1427 blk_t pblk;
1429 if (!inode) {
1430 *phys = block;
1431 return 0;
1434 retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
1435 &inode->i_ext2, NULL, 0, block, &pblk);
1436 *phys = pblk;
1437 return retval;
1438 #endif
1441 static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
1443 struct buffer_head *bh;
1445 bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
1446 if (!bh)
1447 return NULL;
1449 bh->b_ctx = kdev->k_ctx;
1450 if (kdev->k_dev == K_DEV_FS)
1451 bh->b_io = kdev->k_ctx->fs->io;
1452 else
1453 bh->b_io = kdev->k_ctx->journal_io;
1454 bh->b_size = blocksize;
1455 bh->b_blocknr = blocknr;
1457 return bh;
1460 static void sync_blockdev(kdev_t kdev)
1462 io_channel io;
1464 if (kdev->k_dev == K_DEV_FS)
1465 io = kdev->k_ctx->fs->io;
1466 else
1467 io = kdev->k_ctx->journal_io;
1469 io_channel_flush(io);
1472 static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
1474 int retval;
1475 struct buffer_head *bh;
1477 for (; nr > 0; --nr) {
1478 bh = *bhp++;
1479 if (rw == READ && !bh->b_uptodate) {
1480 retval = io_channel_read_blk(bh->b_io,
1481 bh->b_blocknr,
1482 1, bh->b_data);
1483 if (retval) {
1484 bb_error_msg("while reading block %lu",
1485 (unsigned long) bh->b_blocknr);
1486 bh->b_err = retval;
1487 continue;
1489 bh->b_uptodate = 1;
1490 } else if (rw == WRITE && bh->b_dirty) {
1491 retval = io_channel_write_blk(bh->b_io,
1492 bh->b_blocknr,
1493 1, bh->b_data);
1494 if (retval) {
1495 bb_error_msg("while writing block %lu",
1496 (unsigned long) bh->b_blocknr);
1497 bh->b_err = retval;
1498 continue;
1500 bh->b_dirty = 0;
1501 bh->b_uptodate = 1;
1506 static void mark_buffer_dirty(struct buffer_head *bh)
1508 bh->b_dirty = 1;
1511 static inline void mark_buffer_clean(struct buffer_head * bh)
1513 bh->b_dirty = 0;
1516 static void brelse(struct buffer_head *bh)
1518 if (bh->b_dirty)
1519 ll_rw_block(WRITE, 1, &bh);
1520 ext2fs_free_mem(&bh);
1523 static int buffer_uptodate(struct buffer_head *bh)
1525 return bh->b_uptodate;
1528 static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
1530 bh->b_uptodate = val;
1533 static void wait_on_buffer(struct buffer_head *bh)
1535 if (!bh->b_uptodate)
1536 ll_rw_block(READ, 1, &bh);
1540 static void e2fsck_clear_recover(e2fsck_t ctx, int error)
1542 ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
1544 /* if we had an error doing journal recovery, we need a full fsck */
1545 if (error)
1546 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
1547 ext2fs_mark_super_dirty(ctx->fs);
1550 static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
1552 struct ext2_super_block *sb = ctx->fs->super;
1553 struct ext2_super_block jsuper;
1554 struct problem_context pctx;
1555 struct buffer_head *bh;
1556 struct inode *j_inode = NULL;
1557 struct kdev_s *dev_fs = NULL, *dev_journal;
1558 const char *journal_name = NULL;
1559 journal_t *journal = NULL;
1560 errcode_t retval = 0;
1561 io_manager io_ptr = 0;
1562 unsigned long start = 0;
1563 blk_t blk;
1564 int ext_journal = 0;
1565 int tried_backup_jnl = 0;
1566 int i;
1568 clear_problem_context(&pctx);
1570 journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
1571 if (!journal) {
1572 return EXT2_ET_NO_MEMORY;
1575 dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
1576 if (!dev_fs) {
1577 retval = EXT2_ET_NO_MEMORY;
1578 goto errout;
1580 dev_journal = dev_fs+1;
1582 dev_fs->k_ctx = dev_journal->k_ctx = ctx;
1583 dev_fs->k_dev = K_DEV_FS;
1584 dev_journal->k_dev = K_DEV_JOURNAL;
1586 journal->j_dev = dev_journal;
1587 journal->j_fs_dev = dev_fs;
1588 journal->j_inode = NULL;
1589 journal->j_blocksize = ctx->fs->blocksize;
1591 if (uuid_is_null(sb->s_journal_uuid)) {
1592 if (!sb->s_journal_inum)
1593 return EXT2_ET_BAD_INODE_NUM;
1594 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
1595 "journal inode");
1596 if (!j_inode) {
1597 retval = EXT2_ET_NO_MEMORY;
1598 goto errout;
1601 j_inode->i_ctx = ctx;
1602 j_inode->i_ino = sb->s_journal_inum;
1604 if ((retval = ext2fs_read_inode(ctx->fs,
1605 sb->s_journal_inum,
1606 &j_inode->i_ext2))) {
1607 try_backup_journal:
1608 if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
1609 tried_backup_jnl)
1610 goto errout;
1611 memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
1612 memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
1613 EXT2_N_BLOCKS*4);
1614 j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
1615 j_inode->i_ext2.i_links_count = 1;
1616 j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
1617 tried_backup_jnl++;
1619 if (!j_inode->i_ext2.i_links_count ||
1620 !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
1621 retval = EXT2_ET_NO_JOURNAL;
1622 goto try_backup_journal;
1624 if (j_inode->i_ext2.i_size / journal->j_blocksize <
1625 JFS_MIN_JOURNAL_BLOCKS) {
1626 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1627 goto try_backup_journal;
1629 for (i=0; i < EXT2_N_BLOCKS; i++) {
1630 blk = j_inode->i_ext2.i_block[i];
1631 if (!blk) {
1632 if (i < EXT2_NDIR_BLOCKS) {
1633 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1634 goto try_backup_journal;
1636 continue;
1638 if (blk < sb->s_first_data_block ||
1639 blk >= sb->s_blocks_count) {
1640 retval = EXT2_ET_BAD_BLOCK_NUM;
1641 goto try_backup_journal;
1644 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
1646 #ifdef USE_INODE_IO
1647 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
1648 &j_inode->i_ext2,
1649 &journal_name);
1650 if (retval)
1651 goto errout;
1653 io_ptr = inode_io_manager;
1654 #else
1655 journal->j_inode = j_inode;
1656 ctx->journal_io = ctx->fs->io;
1657 if ((retval = journal_bmap(journal, 0, &start)) != 0)
1658 goto errout;
1659 #endif
1660 } else {
1661 ext_journal = 1;
1662 if (!ctx->journal_name) {
1663 char uuid[37];
1665 unparse_uuid(sb->s_journal_uuid, uuid);
1666 ctx->journal_name = get_devname_from_uuid(uuid);
1667 if (!ctx->journal_name)
1668 ctx->journal_name = get_devname_from_device(sb->s_journal_dev);
1670 journal_name = ctx->journal_name;
1672 if (!journal_name) {
1673 fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
1674 return EXT2_ET_LOAD_EXT_JOURNAL;
1677 io_ptr = unix_io_manager;
1680 #ifndef USE_INODE_IO
1681 if (ext_journal)
1682 #endif
1683 retval = io_ptr->open(journal_name, IO_FLAG_RW,
1684 &ctx->journal_io);
1685 if (retval)
1686 goto errout;
1688 io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
1690 if (ext_journal) {
1691 if (ctx->fs->blocksize == 1024)
1692 start = 1;
1693 bh = getblk(dev_journal, start, ctx->fs->blocksize);
1694 if (!bh) {
1695 retval = EXT2_ET_NO_MEMORY;
1696 goto errout;
1698 ll_rw_block(READ, 1, &bh);
1699 if ((retval = bh->b_err) != 0)
1700 goto errout;
1701 memcpy(&jsuper, start ? bh->b_data : bh->b_data + 1024,
1702 sizeof(jsuper));
1703 brelse(bh);
1704 #if BB_BIG_ENDIAN
1705 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
1706 ext2fs_swap_super(&jsuper);
1707 #endif
1708 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
1709 !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
1710 fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
1711 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1712 goto errout;
1714 /* Make sure the journal UUID is correct */
1715 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
1716 sizeof(jsuper.s_uuid))) {
1717 fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
1718 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1719 goto errout;
1722 journal->j_maxlen = jsuper.s_blocks_count;
1723 start++;
1726 if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
1727 retval = EXT2_ET_NO_MEMORY;
1728 goto errout;
1731 journal->j_sb_buffer = bh;
1732 journal->j_superblock = (journal_superblock_t *)bh->b_data;
1734 #ifdef USE_INODE_IO
1735 ext2fs_free_mem(&j_inode);
1736 #endif
1738 *ret_journal = journal;
1739 return 0;
1741 errout:
1742 ext2fs_free_mem(&dev_fs);
1743 ext2fs_free_mem(&j_inode);
1744 ext2fs_free_mem(&journal);
1745 return retval;
1748 static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
1749 struct problem_context *pctx)
1751 struct ext2_super_block *sb = ctx->fs->super;
1752 int recover = ctx->fs->super->s_feature_incompat &
1753 EXT3_FEATURE_INCOMPAT_RECOVER;
1754 int has_journal = ctx->fs->super->s_feature_compat &
1755 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1757 if (has_journal || sb->s_journal_inum) {
1758 /* The journal inode is bogus, remove and force full fsck */
1759 pctx->ino = sb->s_journal_inum;
1760 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
1761 if (has_journal && sb->s_journal_inum)
1762 printf("*** ext3 journal has been deleted - "
1763 "filesystem is now ext2 only ***\n\n");
1764 sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1765 sb->s_journal_inum = 0;
1766 ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
1767 e2fsck_clear_recover(ctx, 1);
1768 return 0;
1770 return EXT2_ET_BAD_INODE_NUM;
1771 } else if (recover) {
1772 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
1773 e2fsck_clear_recover(ctx, 1);
1774 return 0;
1776 return EXT2_ET_UNSUPP_FEATURE;
1778 return 0;
1781 #define V1_SB_SIZE 0x0024
1782 static void clear_v2_journal_fields(journal_t *journal)
1784 e2fsck_t ctx = journal->j_dev->k_ctx;
1785 struct problem_context pctx;
1787 clear_problem_context(&pctx);
1789 if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
1790 return;
1792 memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
1793 ctx->fs->blocksize-V1_SB_SIZE);
1794 mark_buffer_dirty(journal->j_sb_buffer);
1798 static errcode_t e2fsck_journal_load(journal_t *journal)
1800 e2fsck_t ctx = journal->j_dev->k_ctx;
1801 journal_superblock_t *jsb;
1802 struct buffer_head *jbh = journal->j_sb_buffer;
1803 struct problem_context pctx;
1805 clear_problem_context(&pctx);
1807 ll_rw_block(READ, 1, &jbh);
1808 if (jbh->b_err) {
1809 bb_error_msg(_("reading journal superblock"));
1810 return jbh->b_err;
1813 jsb = journal->j_superblock;
1814 /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
1815 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
1816 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1818 switch (ntohl(jsb->s_header.h_blocktype)) {
1819 case JFS_SUPERBLOCK_V1:
1820 journal->j_format_version = 1;
1821 if (jsb->s_feature_compat ||
1822 jsb->s_feature_incompat ||
1823 jsb->s_feature_ro_compat ||
1824 jsb->s_nr_users)
1825 clear_v2_journal_fields(journal);
1826 break;
1828 case JFS_SUPERBLOCK_V2:
1829 journal->j_format_version = 2;
1830 if (ntohl(jsb->s_nr_users) > 1 &&
1831 uuid_is_null(ctx->fs->super->s_journal_uuid))
1832 clear_v2_journal_fields(journal);
1833 if (ntohl(jsb->s_nr_users) > 1) {
1834 fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
1835 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1837 break;
1840 * These should never appear in a journal super block, so if
1841 * they do, the journal is badly corrupted.
1843 case JFS_DESCRIPTOR_BLOCK:
1844 case JFS_COMMIT_BLOCK:
1845 case JFS_REVOKE_BLOCK:
1846 return EXT2_ET_CORRUPT_SUPERBLOCK;
1848 /* If we don't understand the superblock major type, but there
1849 * is a magic number, then it is likely to be a new format we
1850 * just don't understand, so leave it alone. */
1851 default:
1852 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1855 if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
1856 return EXT2_ET_UNSUPP_FEATURE;
1858 if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
1859 return EXT2_ET_RO_UNSUPP_FEATURE;
1861 /* We have now checked whether we know enough about the journal
1862 * format to be able to proceed safely, so any other checks that
1863 * fail we should attempt to recover from. */
1864 if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
1865 bb_error_msg(_("%s: no valid journal superblock found"),
1866 ctx->device_name);
1867 return EXT2_ET_CORRUPT_SUPERBLOCK;
1870 if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
1871 journal->j_maxlen = ntohl(jsb->s_maxlen);
1872 else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
1873 bb_error_msg(_("%s: journal too short"),
1874 ctx->device_name);
1875 return EXT2_ET_CORRUPT_SUPERBLOCK;
1878 journal->j_tail_sequence = ntohl(jsb->s_sequence);
1879 journal->j_transaction_sequence = journal->j_tail_sequence;
1880 journal->j_tail = ntohl(jsb->s_start);
1881 journal->j_first = ntohl(jsb->s_first);
1882 journal->j_last = ntohl(jsb->s_maxlen);
1884 return 0;
1887 static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
1888 journal_t *journal)
1890 char *p;
1891 union {
1892 __u8 uuid[16];
1893 __u32 val[4];
1894 } u;
1895 __u32 new_seq = 0;
1896 int i;
1898 /* Leave a valid existing V1 superblock signature alone.
1899 * Anything unrecognizable we overwrite with a new V2
1900 * signature. */
1902 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
1903 jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
1904 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
1905 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
1908 /* Zero out everything else beyond the superblock header */
1910 p = ((char *) jsb) + sizeof(journal_header_t);
1911 memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
1913 jsb->s_blocksize = htonl(ctx->fs->blocksize);
1914 jsb->s_maxlen = htonl(journal->j_maxlen);
1915 jsb->s_first = htonl(1);
1917 /* Initialize the journal sequence number so that there is "no"
1918 * chance we will find old "valid" transactions in the journal.
1919 * This avoids the need to zero the whole journal (slow to do,
1920 * and risky when we are just recovering the filesystem).
1922 generate_uuid(u.uuid);
1923 for (i = 0; i < 4; i ++)
1924 new_seq ^= u.val[i];
1925 jsb->s_sequence = htonl(new_seq);
1927 mark_buffer_dirty(journal->j_sb_buffer);
1928 ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
1931 static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
1932 journal_t *journal,
1933 struct problem_context *pctx)
1935 struct ext2_super_block *sb = ctx->fs->super;
1936 int recover = ctx->fs->super->s_feature_incompat &
1937 EXT3_FEATURE_INCOMPAT_RECOVER;
1939 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1940 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
1941 e2fsck_journal_reset_super(ctx, journal->j_superblock,
1942 journal);
1943 journal->j_transaction_sequence = 1;
1944 e2fsck_clear_recover(ctx, recover);
1945 return 0;
1947 return EXT2_ET_CORRUPT_SUPERBLOCK;
1948 } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
1949 return EXT2_ET_CORRUPT_SUPERBLOCK;
1951 return 0;
1954 static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
1955 int reset, int drop)
1957 journal_superblock_t *jsb;
1959 if (drop)
1960 mark_buffer_clean(journal->j_sb_buffer);
1961 else if (!(ctx->options & E2F_OPT_READONLY)) {
1962 jsb = journal->j_superblock;
1963 jsb->s_sequence = htonl(journal->j_transaction_sequence);
1964 if (reset)
1965 jsb->s_start = 0; /* this marks the journal as empty */
1966 mark_buffer_dirty(journal->j_sb_buffer);
1968 brelse(journal->j_sb_buffer);
1970 if (ctx->journal_io) {
1971 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1972 io_channel_close(ctx->journal_io);
1973 ctx->journal_io = 0;
1976 #ifndef USE_INODE_IO
1977 ext2fs_free_mem(&journal->j_inode);
1978 #endif
1979 ext2fs_free_mem(&journal->j_fs_dev);
1980 ext2fs_free_mem(&journal);
1984 * This function makes sure that the superblock fields regarding the
1985 * journal are consistent.
1987 static int e2fsck_check_ext3_journal(e2fsck_t ctx)
1989 struct ext2_super_block *sb = ctx->fs->super;
1990 journal_t *journal;
1991 int recover = ctx->fs->super->s_feature_incompat &
1992 EXT3_FEATURE_INCOMPAT_RECOVER;
1993 struct problem_context pctx;
1994 problem_t problem;
1995 int reset = 0, force_fsck = 0;
1996 int retval;
1998 /* If we don't have any journal features, don't do anything more */
1999 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
2000 !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
2001 uuid_is_null(sb->s_journal_uuid))
2002 return 0;
2004 clear_problem_context(&pctx);
2005 pctx.num = sb->s_journal_inum;
2007 retval = e2fsck_get_journal(ctx, &journal);
2008 if (retval) {
2009 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
2010 (retval == EXT2_ET_BAD_BLOCK_NUM) ||
2011 (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
2012 (retval == EXT2_ET_NO_JOURNAL))
2013 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
2014 return retval;
2017 retval = e2fsck_journal_load(journal);
2018 if (retval) {
2019 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
2020 ((retval == EXT2_ET_UNSUPP_FEATURE) &&
2021 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
2022 &pctx))) ||
2023 ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
2024 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
2025 &pctx))) ||
2026 ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
2027 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
2028 retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
2029 &pctx);
2030 e2fsck_journal_release(ctx, journal, 0, 1);
2031 return retval;
2035 * We want to make the flags consistent here. We will not leave with
2036 * needs_recovery set but has_journal clear. We can't get in a loop
2037 * with -y, -n, or -p, only if a user isn't making up their mind.
2039 no_has_journal:
2040 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
2041 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
2042 pctx.str = "inode";
2043 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
2044 if (recover &&
2045 !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
2046 goto no_has_journal;
2048 * Need a full fsck if we are releasing a
2049 * journal stored on a reserved inode.
2051 force_fsck = recover ||
2052 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
2053 /* Clear all of the journal fields */
2054 sb->s_journal_inum = 0;
2055 sb->s_journal_dev = 0;
2056 memset(sb->s_journal_uuid, 0,
2057 sizeof(sb->s_journal_uuid));
2058 e2fsck_clear_recover(ctx, force_fsck);
2059 } else if (!(ctx->options & E2F_OPT_READONLY)) {
2060 sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2061 ext2fs_mark_super_dirty(ctx->fs);
2065 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
2066 !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
2067 journal->j_superblock->s_start != 0) {
2068 /* Print status information */
2069 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
2070 if (ctx->superblock)
2071 problem = PR_0_JOURNAL_RUN_DEFAULT;
2072 else
2073 problem = PR_0_JOURNAL_RUN;
2074 if (fix_problem(ctx, problem, &pctx)) {
2075 ctx->options |= E2F_OPT_FORCE;
2076 sb->s_feature_incompat |=
2077 EXT3_FEATURE_INCOMPAT_RECOVER;
2078 ext2fs_mark_super_dirty(ctx->fs);
2079 } else if (fix_problem(ctx,
2080 PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
2081 reset = 1;
2082 sb->s_state &= ~EXT2_VALID_FS;
2083 ext2fs_mark_super_dirty(ctx->fs);
2086 * If the user answers no to the above question, we
2087 * ignore the fact that journal apparently has data;
2088 * accidentally replaying over valid data would be far
2089 * worse than skipping a questionable recovery.
2091 * XXX should we abort with a fatal error here? What
2092 * will the ext3 kernel code do if a filesystem with
2093 * !NEEDS_RECOVERY but with a non-zero
2094 * journal->j_superblock->s_start is mounted?
2098 e2fsck_journal_release(ctx, journal, reset, 0);
2099 return retval;
2102 static errcode_t recover_ext3_journal(e2fsck_t ctx)
2104 journal_t *journal;
2105 int retval;
2107 journal_init_revoke_caches();
2108 retval = e2fsck_get_journal(ctx, &journal);
2109 if (retval)
2110 return retval;
2112 retval = e2fsck_journal_load(journal);
2113 if (retval)
2114 goto errout;
2116 retval = journal_init_revoke(journal, 1024);
2117 if (retval)
2118 goto errout;
2120 retval = -journal_recover(journal);
2121 if (retval)
2122 goto errout;
2124 if (journal->j_superblock->s_errno) {
2125 ctx->fs->super->s_state |= EXT2_ERROR_FS;
2126 ext2fs_mark_super_dirty(ctx->fs);
2127 journal->j_superblock->s_errno = 0;
2128 mark_buffer_dirty(journal->j_sb_buffer);
2131 errout:
2132 journal_destroy_revoke(journal);
2133 journal_destroy_revoke_caches();
2134 e2fsck_journal_release(ctx, journal, 1, 0);
2135 return retval;
2138 static int e2fsck_run_ext3_journal(e2fsck_t ctx)
2140 io_manager io_ptr = ctx->fs->io->manager;
2141 int blocksize = ctx->fs->blocksize;
2142 errcode_t retval, recover_retval;
2144 printf(_("%s: recovering journal\n"), ctx->device_name);
2145 if (ctx->options & E2F_OPT_READONLY) {
2146 printf(_("%s: won't do journal recovery while read-only\n"),
2147 ctx->device_name);
2148 return EXT2_ET_FILE_RO;
2151 if (ctx->fs->flags & EXT2_FLAG_DIRTY)
2152 ext2fs_flush(ctx->fs); /* Force out any modifications */
2154 recover_retval = recover_ext3_journal(ctx);
2157 * Reload the filesystem context to get up-to-date data from disk
2158 * because journal recovery will change the filesystem under us.
2160 ext2fs_close(ctx->fs);
2161 retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
2162 ctx->superblock, blocksize, io_ptr,
2163 &ctx->fs);
2165 if (retval) {
2166 bb_error_msg(_("while trying to re-open %s"),
2167 ctx->device_name);
2168 bb_error_msg_and_die(0);
2170 ctx->fs->priv_data = ctx;
2172 /* Set the superblock flags */
2173 e2fsck_clear_recover(ctx, recover_retval);
2174 return recover_retval;
2178 * This function will move the journal inode from a visible file in
2179 * the filesystem directory hierarchy to the reserved inode if necessary.
2181 static const char *const journal_names[] = {
2182 ".journal", "journal", ".journal.dat", "journal.dat", 0 };
2184 static void e2fsck_move_ext3_journal(e2fsck_t ctx)
2186 struct ext2_super_block *sb = ctx->fs->super;
2187 struct problem_context pctx;
2188 struct ext2_inode inode;
2189 ext2_filsys fs = ctx->fs;
2190 ext2_ino_t ino;
2191 errcode_t retval;
2192 const char *const * cpp;
2193 int group, mount_flags;
2195 clear_problem_context(&pctx);
2198 * If the filesystem is opened read-only, or there is no
2199 * journal, then do nothing.
2201 if ((ctx->options & E2F_OPT_READONLY) ||
2202 (sb->s_journal_inum == 0) ||
2203 !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2204 return;
2207 * Read in the journal inode
2209 if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
2210 return;
2213 * If it's necessary to backup the journal inode, do so.
2215 if ((sb->s_jnl_backup_type == 0) ||
2216 ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
2217 memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
2218 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
2219 memcpy(sb->s_jnl_blocks, inode.i_block,
2220 EXT2_N_BLOCKS*4);
2221 sb->s_jnl_blocks[16] = inode.i_size;
2222 sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2223 ext2fs_mark_super_dirty(fs);
2224 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2229 * If the journal is already the hidden inode, then do nothing
2231 if (sb->s_journal_inum == EXT2_JOURNAL_INO)
2232 return;
2235 * The journal inode had better have only one link and not be readable.
2237 if (inode.i_links_count != 1)
2238 return;
2241 * If the filesystem is mounted, or we can't tell whether
2242 * or not it's mounted, do nothing.
2244 retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
2245 if (retval || (mount_flags & EXT2_MF_MOUNTED))
2246 return;
2249 * If we can't find the name of the journal inode, then do
2250 * nothing.
2252 for (cpp = journal_names; *cpp; cpp++) {
2253 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
2254 strlen(*cpp), 0, &ino);
2255 if ((retval == 0) && (ino == sb->s_journal_inum))
2256 break;
2258 if (*cpp == 0)
2259 return;
2261 /* We need the inode bitmap to be loaded */
2262 retval = ext2fs_read_bitmaps(fs);
2263 if (retval)
2264 return;
2266 pctx.str = *cpp;
2267 if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
2268 return;
2271 * OK, we've done all the checks, let's actually move the
2272 * journal inode. Errors at this point mean we need to force
2273 * an ext2 filesystem check.
2275 if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
2276 goto err_out;
2277 if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
2278 goto err_out;
2279 sb->s_journal_inum = EXT2_JOURNAL_INO;
2280 ext2fs_mark_super_dirty(fs);
2281 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2282 inode.i_links_count = 0;
2283 inode.i_dtime = time(NULL);
2284 if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
2285 goto err_out;
2287 group = ext2fs_group_of_ino(fs, ino);
2288 ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
2289 ext2fs_mark_ib_dirty(fs);
2290 fs->group_desc[group].bg_free_inodes_count++;
2291 fs->super->s_free_inodes_count++;
2292 return;
2294 err_out:
2295 pctx.errcode = retval;
2296 fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
2297 fs->super->s_state &= ~EXT2_VALID_FS;
2298 ext2fs_mark_super_dirty(fs);
2302 * message.c --- print e2fsck messages (with compression)
2304 * print_e2fsck_message() prints a message to the user, using
2305 * compression techniques and expansions of abbreviations.
2307 * The following % expansions are supported:
2309 * %b <blk> block number
2310 * %B <blkcount> integer
2311 * %c <blk2> block number
2312 * %Di <dirent>->ino inode number
2313 * %Dn <dirent>->name string
2314 * %Dr <dirent>->rec_len
2315 * %Dl <dirent>->name_len
2316 * %Dt <dirent>->filetype
2317 * %d <dir> inode number
2318 * %g <group> integer
2319 * %i <ino> inode number
2320 * %Is <inode> -> i_size
2321 * %IS <inode> -> i_extra_isize
2322 * %Ib <inode> -> i_blocks
2323 * %Il <inode> -> i_links_count
2324 * %Im <inode> -> i_mode
2325 * %IM <inode> -> i_mtime
2326 * %IF <inode> -> i_faddr
2327 * %If <inode> -> i_file_acl
2328 * %Id <inode> -> i_dir_acl
2329 * %Iu <inode> -> i_uid
2330 * %Ig <inode> -> i_gid
2331 * %j <ino2> inode number
2332 * %m <com_err error message>
2333 * %N <num>
2334 * %p ext2fs_get_pathname of directory <ino>
2335 * %P ext2fs_get_pathname of <dirent>->ino with <ino2> as
2336 * the containing directory. (If dirent is NULL
2337 * then return the pathname of directory <ino2>)
2338 * %q ext2fs_get_pathname of directory <dir>
2339 * %Q ext2fs_get_pathname of directory <ino> with <dir> as
2340 * the containing directory.
2341 * %s <str> miscellaneous string
2342 * %S backup superblock
2343 * %X <num> hexadecimal format
2345 * The following '@' expansions are supported:
2347 * @a extended attribute
2348 * @A error allocating
2349 * @b block
2350 * @B bitmap
2351 * @c compress
2352 * @C conflicts with some other fs block
2353 * @D deleted
2354 * @d directory
2355 * @e entry
2356 * @E Entry '%Dn' in %p (%i)
2357 * @f filesystem
2358 * @F for @i %i (%Q) is
2359 * @g group
2360 * @h HTREE directory inode
2361 * @i inode
2362 * @I illegal
2363 * @j journal
2364 * @l lost+found
2365 * @L is a link
2366 * @m multiply-claimed
2367 * @n invalid
2368 * @o orphaned
2369 * @p problem in
2370 * @r root inode
2371 * @s should be
2372 * @S superblock
2373 * @u unattached
2374 * @v device
2375 * @z zero-length
2380 * This structure defines the abbreviations used by the text strings
2381 * below. The first character in the string is the index letter. An
2382 * abbreviation of the form '@<i>' is expanded by looking up the index
2383 * letter <i> in the table below.
2385 static const char *const abbrevs[] = {
2386 N_("aextended attribute"),
2387 N_("Aerror allocating"),
2388 N_("bblock"),
2389 N_("Bbitmap"),
2390 N_("ccompress"),
2391 N_("Cconflicts with some other fs @b"),
2392 N_("iinode"),
2393 N_("Iillegal"),
2394 N_("jjournal"),
2395 N_("Ddeleted"),
2396 N_("ddirectory"),
2397 N_("eentry"),
2398 N_("E@e '%Dn' in %p (%i)"),
2399 N_("ffilesystem"),
2400 N_("Ffor @i %i (%Q) is"),
2401 N_("ggroup"),
2402 N_("hHTREE @d @i"),
2403 N_("llost+found"),
2404 N_("Lis a link"),
2405 N_("mmultiply-claimed"),
2406 N_("ninvalid"),
2407 N_("oorphaned"),
2408 N_("pproblem in"),
2409 N_("rroot @i"),
2410 N_("sshould be"),
2411 N_("Ssuper@b"),
2412 N_("uunattached"),
2413 N_("vdevice"),
2414 N_("zzero-length"),
2415 "@@",
2420 * Give more user friendly names to the "special" inodes.
2422 #define num_special_inodes 11
2423 static const char *const special_inode_name[] =
2425 N_("<The NULL inode>"), /* 0 */
2426 N_("<The bad blocks inode>"), /* 1 */
2427 "/", /* 2 */
2428 N_("<The ACL index inode>"), /* 3 */
2429 N_("<The ACL data inode>"), /* 4 */
2430 N_("<The boot loader inode>"), /* 5 */
2431 N_("<The undelete directory inode>"), /* 6 */
2432 N_("<The group descriptor inode>"), /* 7 */
2433 N_("<The journal inode>"), /* 8 */
2434 N_("<Reserved inode 9>"), /* 9 */
2435 N_("<Reserved inode 10>"), /* 10 */
2439 * This function does "safe" printing. It will convert non-printable
2440 * ASCII characters using '^' and M- notation.
2442 static void safe_print(const char *cp, int len)
2444 unsigned char ch;
2446 if (len < 0)
2447 len = strlen(cp);
2449 while (len--) {
2450 ch = *cp++;
2451 if (ch > 128) {
2452 fputs("M-", stdout);
2453 ch -= 128;
2455 if ((ch < 32) || (ch == 0x7f)) {
2456 bb_putchar('^');
2457 ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
2459 bb_putchar(ch);
2465 * This function prints a pathname, using the ext2fs_get_pathname
2466 * function
2468 static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
2470 errcode_t retval;
2471 char *path;
2473 if (!dir && (ino < num_special_inodes)) {
2474 fputs(_(special_inode_name[ino]), stdout);
2475 return;
2478 retval = ext2fs_get_pathname(fs, dir, ino, &path);
2479 if (retval)
2480 fputs("???", stdout);
2481 else {
2482 safe_print(path, -1);
2483 ext2fs_free_mem(&path);
2487 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2488 struct problem_context *pctx, int first);
2490 * This function handles the '@' expansion. We allow recursive
2491 * expansion; an @ expression can contain further '@' and '%'
2492 * expressions.
2494 static void expand_at_expression(e2fsck_t ctx, char ch,
2495 struct problem_context *pctx,
2496 int *first)
2498 const char *const *cpp;
2499 const char *str;
2501 /* Search for the abbreviation */
2502 for (cpp = abbrevs; *cpp; cpp++) {
2503 if (ch == *cpp[0])
2504 break;
2506 if (*cpp) {
2507 str = _(*cpp) + 1;
2508 if (*first && islower(*str)) {
2509 *first = 0;
2510 bb_putchar(toupper(*str++));
2512 print_e2fsck_message(ctx, str, pctx, *first);
2513 } else
2514 printf("@%c", ch);
2518 * This function expands '%IX' expressions
2520 static void expand_inode_expression(char ch,
2521 struct problem_context *ctx)
2523 struct ext2_inode *inode;
2524 struct ext2_inode_large *large_inode;
2525 char * time_str;
2526 time_t t;
2527 int do_gmt = -1;
2529 if (!ctx || !ctx->inode)
2530 goto no_inode;
2532 inode = ctx->inode;
2533 large_inode = (struct ext2_inode_large *) inode;
2535 switch (ch) {
2536 case 's':
2537 if (LINUX_S_ISDIR(inode->i_mode))
2538 printf("%u", inode->i_size);
2539 else {
2540 printf("%"PRIu64, (inode->i_size |
2541 ((uint64_t) inode->i_size_high << 32)));
2543 break;
2544 case 'S':
2545 printf("%u", large_inode->i_extra_isize);
2546 break;
2547 case 'b':
2548 printf("%u", inode->i_blocks);
2549 break;
2550 case 'l':
2551 printf("%d", inode->i_links_count);
2552 break;
2553 case 'm':
2554 printf("0%o", inode->i_mode);
2555 break;
2556 case 'M':
2557 /* The diet libc doesn't respect the TZ environemnt variable */
2558 if (do_gmt == -1) {
2559 time_str = getenv("TZ");
2560 if (!time_str)
2561 time_str = (char *)"";
2562 do_gmt = !strcmp(time_str, "GMT");
2564 t = inode->i_mtime;
2565 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
2566 printf("%.24s", time_str);
2567 break;
2568 case 'F':
2569 printf("%u", inode->i_faddr);
2570 break;
2571 case 'f':
2572 printf("%u", inode->i_file_acl);
2573 break;
2574 case 'd':
2575 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
2576 inode->i_dir_acl : 0));
2577 break;
2578 case 'u':
2579 printf("%d", (inode->i_uid |
2580 (inode->osd2.linux2.l_i_uid_high << 16)));
2581 break;
2582 case 'g':
2583 printf("%d", (inode->i_gid |
2584 (inode->osd2.linux2.l_i_gid_high << 16)));
2585 break;
2586 default:
2587 no_inode:
2588 printf("%%I%c", ch);
2589 break;
2594 * This function expands '%dX' expressions
2596 static void expand_dirent_expression(char ch,
2597 struct problem_context *ctx)
2599 struct ext2_dir_entry *dirent;
2600 int len;
2602 if (!ctx || !ctx->dirent)
2603 goto no_dirent;
2605 dirent = ctx->dirent;
2607 switch (ch) {
2608 case 'i':
2609 printf("%u", dirent->inode);
2610 break;
2611 case 'n':
2612 len = dirent->name_len & 0xFF;
2613 if (len > EXT2_NAME_LEN)
2614 len = EXT2_NAME_LEN;
2615 if (len > dirent->rec_len)
2616 len = dirent->rec_len;
2617 safe_print(dirent->name, len);
2618 break;
2619 case 'r':
2620 printf("%u", dirent->rec_len);
2621 break;
2622 case 'l':
2623 printf("%u", dirent->name_len & 0xFF);
2624 break;
2625 case 't':
2626 printf("%u", dirent->name_len >> 8);
2627 break;
2628 default:
2629 no_dirent:
2630 printf("%%D%c", ch);
2631 break;
2635 static void expand_percent_expression(ext2_filsys fs, char ch,
2636 struct problem_context *ctx)
2638 if (!ctx)
2639 goto no_context;
2641 switch (ch) {
2642 case '%':
2643 bb_putchar('%');
2644 break;
2645 case 'b':
2646 printf("%u", ctx->blk);
2647 break;
2648 case 'B':
2649 printf("%"PRIi64, ctx->blkcount);
2650 break;
2651 case 'c':
2652 printf("%u", ctx->blk2);
2653 break;
2654 case 'd':
2655 printf("%u", ctx->dir);
2656 break;
2657 case 'g':
2658 printf("%d", ctx->group);
2659 break;
2660 case 'i':
2661 printf("%u", ctx->ino);
2662 break;
2663 case 'j':
2664 printf("%u", ctx->ino2);
2665 break;
2666 case 'm':
2667 fputs(error_message(ctx->errcode), stdout);
2668 break;
2669 case 'N':
2670 printf("%"PRIi64, ctx->num);
2671 break;
2672 case 'p':
2673 print_pathname(fs, ctx->ino, 0);
2674 break;
2675 case 'P':
2676 print_pathname(fs, ctx->ino2,
2677 ctx->dirent ? ctx->dirent->inode : 0);
2678 break;
2679 case 'q':
2680 print_pathname(fs, ctx->dir, 0);
2681 break;
2682 case 'Q':
2683 print_pathname(fs, ctx->dir, ctx->ino);
2684 break;
2685 case 'S':
2686 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
2687 break;
2688 case 's':
2689 fputs((ctx->str ? ctx->str : "NULL"), stdout);
2690 break;
2691 case 'X':
2692 printf("0x%"PRIi64, ctx->num);
2693 break;
2694 default:
2695 no_context:
2696 printf("%%%c", ch);
2697 break;
2702 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2703 struct problem_context *pctx, int first)
2705 ext2_filsys fs = ctx->fs;
2706 const char * cp;
2707 int i;
2709 e2fsck_clear_progbar(ctx);
2710 for (cp = msg; *cp; cp++) {
2711 if (cp[0] == '@') {
2712 cp++;
2713 expand_at_expression(ctx, *cp, pctx, &first);
2714 } else if (cp[0] == '%' && cp[1] == 'I') {
2715 cp += 2;
2716 expand_inode_expression(*cp, pctx);
2717 } else if (cp[0] == '%' && cp[1] == 'D') {
2718 cp += 2;
2719 expand_dirent_expression(*cp, pctx);
2720 } else if ((cp[0] == '%')) {
2721 cp++;
2722 expand_percent_expression(fs, *cp, pctx);
2723 } else {
2724 for (i=0; cp[i]; i++)
2725 if ((cp[i] == '@') || cp[i] == '%')
2726 break;
2727 printf("%.*s", i, cp);
2728 cp += i-1;
2730 first = 0;
2736 * region.c --- code which manages allocations within a region.
2739 struct region_el {
2740 region_addr_t start;
2741 region_addr_t end;
2742 struct region_el *next;
2745 struct region_struct {
2746 region_addr_t min;
2747 region_addr_t max;
2748 struct region_el *allocated;
2751 static region_t region_create(region_addr_t min, region_addr_t max)
2753 region_t region;
2755 region = xzalloc(sizeof(struct region_struct));
2756 region->min = min;
2757 region->max = max;
2758 return region;
2761 static void region_free(region_t region)
2763 struct region_el *r, *next;
2765 for (r = region->allocated; r; r = next) {
2766 next = r->next;
2767 free(r);
2769 memset(region, 0, sizeof(struct region_struct));
2770 free(region);
2773 static int region_allocate(region_t region, region_addr_t start, int n)
2775 struct region_el *r, *new_region, *prev, *next;
2776 region_addr_t end;
2778 end = start+n;
2779 if ((start < region->min) || (end > region->max))
2780 return -1;
2781 if (n == 0)
2782 return 1;
2785 * Search through the linked list. If we find that it
2786 * conflicts witih something that's already allocated, return
2787 * 1; if we can find an existing region which we can grow, do
2788 * so. Otherwise, stop when we find the appropriate place
2789 * insert a new region element into the linked list.
2791 for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
2792 if (((start >= r->start) && (start < r->end)) ||
2793 ((end > r->start) && (end <= r->end)) ||
2794 ((start <= r->start) && (end >= r->end)))
2795 return 1;
2796 if (end == r->start) {
2797 r->start = start;
2798 return 0;
2800 if (start == r->end) {
2801 if ((next = r->next)) {
2802 if (end > next->start)
2803 return 1;
2804 if (end == next->start) {
2805 r->end = next->end;
2806 r->next = next->next;
2807 free(next);
2808 return 0;
2811 r->end = end;
2812 return 0;
2814 if (start < r->start)
2815 break;
2818 * Insert a new region element structure into the linked list
2820 new_region = xmalloc(sizeof(struct region_el));
2821 new_region->start = start;
2822 new_region->end = start + n;
2823 new_region->next = r;
2824 if (prev)
2825 prev->next = new_region;
2826 else
2827 region->allocated = new_region;
2828 return 0;
2832 * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
2834 * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
2835 * and applies the following tests to each inode:
2837 * - The mode field of the inode must be legal.
2838 * - The size and block count fields of the inode are correct.
2839 * - A data block must not be used by another inode
2841 * Pass 1 also gathers the collects the following information:
2843 * - A bitmap of which inodes are in use. (inode_used_map)
2844 * - A bitmap of which inodes are directories. (inode_dir_map)
2845 * - A bitmap of which inodes are regular files. (inode_reg_map)
2846 * - A bitmap of which inodes have bad fields. (inode_bad_map)
2847 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
2848 * - A bitmap of which blocks are in use. (block_found_map)
2849 * - A bitmap of which blocks are in use by two inodes (block_dup_map)
2850 * - The data blocks of the directory inodes. (dir_map)
2852 * Pass 1 is designed to stash away enough information so that the
2853 * other passes should not need to read in the inode information
2854 * during the normal course of a filesystem check. (Althogh if an
2855 * inconsistency is detected, other passes may need to read in an
2856 * inode to fix it.)
2858 * Note that pass 1B will be invoked if there are any duplicate blocks
2859 * found.
2863 static int process_block(ext2_filsys fs, blk_t *blocknr,
2864 e2_blkcnt_t blockcnt, blk_t ref_blk,
2865 int ref_offset, void *priv_data);
2866 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
2867 e2_blkcnt_t blockcnt, blk_t ref_blk,
2868 int ref_offset, void *priv_data);
2869 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
2870 char *block_buf);
2871 static void mark_table_blocks(e2fsck_t ctx);
2872 static void alloc_imagic_map(e2fsck_t ctx);
2873 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
2874 static void handle_fs_bad_blocks(e2fsck_t ctx);
2875 static void process_inodes(e2fsck_t ctx, char *block_buf);
2876 static int process_inode_cmp(const void *a, const void *b);
2877 static errcode_t scan_callback(ext2_filsys fs,
2878 dgrp_t group, void * priv_data);
2879 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
2880 char *block_buf, int adjust_sign);
2881 /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
2883 static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
2884 struct ext2_inode * inode, int bufsize,
2885 const char *proc);
2887 struct process_block_struct_1 {
2888 ext2_ino_t ino;
2889 unsigned is_dir:1, is_reg:1, clear:1, suppress:1,
2890 fragmented:1, compressed:1, bbcheck:1;
2891 blk_t num_blocks;
2892 blk_t max_blocks;
2893 e2_blkcnt_t last_block;
2894 int num_illegal_blocks;
2895 blk_t previous_block;
2896 struct ext2_inode *inode;
2897 struct problem_context *pctx;
2898 ext2fs_block_bitmap fs_meta_blocks;
2899 e2fsck_t ctx;
2902 struct process_inode_block {
2903 ext2_ino_t ino;
2904 struct ext2_inode inode;
2907 struct scan_callback_struct {
2908 e2fsck_t ctx;
2909 char *block_buf;
2913 * For the inodes to process list.
2915 static struct process_inode_block *inodes_to_process;
2916 static int process_inode_count;
2918 static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
2919 EXT2_MIN_BLOCK_LOG_SIZE + 1];
2922 * Free all memory allocated by pass1 in preparation for restarting
2923 * things.
2925 static void unwind_pass1(void)
2927 ext2fs_free_mem(&inodes_to_process);
2931 * Check to make sure a device inode is real. Returns 1 if the device
2932 * checks out, 0 if not.
2934 * Note: this routine is now also used to check FIFO's and Sockets,
2935 * since they have the same requirement; the i_block fields should be
2936 * zero.
2938 static int
2939 e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
2941 int i;
2944 * If i_blocks is non-zero, or the index flag is set, then
2945 * this is a bogus device/fifo/socket
2947 if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
2948 (inode->i_flags & EXT2_INDEX_FL))
2949 return 0;
2952 * We should be able to do the test below all the time, but
2953 * because the kernel doesn't forcibly clear the device
2954 * inode's additional i_block fields, there are some rare
2955 * occasions when a legitimate device inode will have non-zero
2956 * additional i_block fields. So for now, we only complain
2957 * when the immutable flag is set, which should never happen
2958 * for devices. (And that's when the problem is caused, since
2959 * you can't set or clear immutable flags for devices.) Once
2960 * the kernel has been fixed we can change this...
2962 if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
2963 for (i=4; i < EXT2_N_BLOCKS; i++)
2964 if (inode->i_block[i])
2965 return 0;
2967 return 1;
2971 * Check to make sure a symlink inode is real. Returns 1 if the symlink
2972 * checks out, 0 if not.
2974 static int
2975 e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
2977 unsigned int len;
2978 int i;
2979 blk_t blocks;
2981 if ((inode->i_size_high || inode->i_size == 0) ||
2982 (inode->i_flags & EXT2_INDEX_FL))
2983 return 0;
2985 blocks = ext2fs_inode_data_blocks(fs, inode);
2986 if (blocks) {
2987 if ((inode->i_size >= fs->blocksize) ||
2988 (blocks != fs->blocksize >> 9) ||
2989 (inode->i_block[0] < fs->super->s_first_data_block) ||
2990 (inode->i_block[0] >= fs->super->s_blocks_count))
2991 return 0;
2993 for (i = 1; i < EXT2_N_BLOCKS; i++)
2994 if (inode->i_block[i])
2995 return 0;
2997 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
2998 return 0;
3000 len = strnlen(buf, fs->blocksize);
3001 if (len == fs->blocksize)
3002 return 0;
3003 } else {
3004 if (inode->i_size >= sizeof(inode->i_block))
3005 return 0;
3007 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
3008 if (len == sizeof(inode->i_block))
3009 return 0;
3011 if (len != inode->i_size)
3012 return 0;
3013 return 1;
3017 * If the immutable (or append-only) flag is set on the inode, offer
3018 * to clear it.
3020 #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
3021 static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
3023 if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
3024 return;
3026 if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
3027 return;
3029 pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
3030 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3034 * If device, fifo or socket, check size is zero -- if not offer to
3035 * clear it
3037 static void check_size(e2fsck_t ctx, struct problem_context *pctx)
3039 struct ext2_inode *inode = pctx->inode;
3041 if ((inode->i_size == 0) && (inode->i_size_high == 0))
3042 return;
3044 if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
3045 return;
3047 inode->i_size = 0;
3048 inode->i_size_high = 0;
3049 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3052 static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
3054 struct ext2_super_block *sb = ctx->fs->super;
3055 struct ext2_inode_large *inode;
3056 struct ext2_ext_attr_entry *entry;
3057 char *start, *end;
3058 int storage_size, remain, offs;
3059 int problem = 0;
3061 inode = (struct ext2_inode_large *) pctx->inode;
3062 storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
3063 inode->i_extra_isize;
3064 start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3065 inode->i_extra_isize + sizeof(__u32);
3066 end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
3067 entry = (struct ext2_ext_attr_entry *) start;
3069 /* scan all entry's headers first */
3071 /* take finish entry 0UL into account */
3072 remain = storage_size - sizeof(__u32);
3073 offs = end - start;
3075 while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
3077 /* header eats this space */
3078 remain -= sizeof(struct ext2_ext_attr_entry);
3080 /* is attribute name valid? */
3081 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
3082 pctx->num = entry->e_name_len;
3083 problem = PR_1_ATTR_NAME_LEN;
3084 goto fix;
3087 /* attribute len eats this space */
3088 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
3090 /* check value size */
3091 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
3092 pctx->num = entry->e_value_size;
3093 problem = PR_1_ATTR_VALUE_SIZE;
3094 goto fix;
3097 /* check value placement */
3098 if (entry->e_value_offs +
3099 EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
3100 printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
3101 pctx->num = entry->e_value_offs;
3102 problem = PR_1_ATTR_VALUE_OFFSET;
3103 goto fix;
3106 /* e_value_block must be 0 in inode's ea */
3107 if (entry->e_value_block != 0) {
3108 pctx->num = entry->e_value_block;
3109 problem = PR_1_ATTR_VALUE_BLOCK;
3110 goto fix;
3113 /* e_hash must be 0 in inode's ea */
3114 if (entry->e_hash != 0) {
3115 pctx->num = entry->e_hash;
3116 problem = PR_1_ATTR_HASH;
3117 goto fix;
3120 remain -= entry->e_value_size;
3121 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
3123 entry = EXT2_EXT_ATTR_NEXT(entry);
3125 fix:
3127 * it seems like a corruption. it's very unlikely we could repair
3128 * EA(s) in automatic fashion -bzzz
3130 if (problem == 0 || !fix_problem(ctx, problem, pctx))
3131 return;
3133 /* simple remove all possible EA(s) */
3134 *((__u32 *)start) = 0UL;
3135 e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
3136 EXT2_INODE_SIZE(sb), "pass1");
3139 static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
3141 struct ext2_super_block *sb = ctx->fs->super;
3142 struct ext2_inode_large *inode;
3143 __u32 *eamagic;
3144 int min, max;
3146 inode = (struct ext2_inode_large *) pctx->inode;
3147 if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
3148 /* this isn't large inode. so, nothing to check */
3149 return;
3152 /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
3153 min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
3154 max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
3156 * For now we will allow i_extra_isize to be 0, but really
3157 * implementations should never allow i_extra_isize to be 0
3159 if (inode->i_extra_isize &&
3160 (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
3161 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
3162 return;
3163 inode->i_extra_isize = min;
3164 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
3165 EXT2_INODE_SIZE(sb), "pass1");
3166 return;
3169 eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3170 inode->i_extra_isize);
3171 if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
3172 /* it seems inode has an extended attribute(s) in body */
3173 check_ea_in_inode(ctx, pctx);
3177 static void e2fsck_pass1(e2fsck_t ctx)
3179 int i;
3180 __u64 max_sizes;
3181 ext2_filsys fs = ctx->fs;
3182 ext2_ino_t ino;
3183 struct ext2_inode *inode;
3184 ext2_inode_scan scan;
3185 char *block_buf;
3186 unsigned char frag, fsize;
3187 struct problem_context pctx;
3188 struct scan_callback_struct scan_struct;
3189 struct ext2_super_block *sb = ctx->fs->super;
3190 int imagic_fs;
3191 int busted_fs_time = 0;
3192 int inode_size;
3194 clear_problem_context(&pctx);
3196 if (!(ctx->options & E2F_OPT_PREEN))
3197 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
3199 if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
3200 !(ctx->options & E2F_OPT_NO)) {
3201 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
3202 ctx->dirs_to_hash = 0;
3205 /* Pass 1 */
3207 #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
3209 for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
3210 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
3211 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
3212 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
3213 max_sizes = (max_sizes * (1UL << i)) - 1;
3214 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
3216 #undef EXT2_BPP
3218 imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
3221 * Allocate bitmaps structures
3223 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
3224 &ctx->inode_used_map);
3225 if (pctx.errcode) {
3226 pctx.num = 1;
3227 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3228 ctx->flags |= E2F_FLAG_ABORT;
3229 return;
3231 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3232 _("directory inode map"), &ctx->inode_dir_map);
3233 if (pctx.errcode) {
3234 pctx.num = 2;
3235 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3236 ctx->flags |= E2F_FLAG_ABORT;
3237 return;
3239 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3240 _("regular file inode map"), &ctx->inode_reg_map);
3241 if (pctx.errcode) {
3242 pctx.num = 6;
3243 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3244 ctx->flags |= E2F_FLAG_ABORT;
3245 return;
3247 pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
3248 &ctx->block_found_map);
3249 if (pctx.errcode) {
3250 pctx.num = 1;
3251 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3252 ctx->flags |= E2F_FLAG_ABORT;
3253 return;
3255 pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
3256 &ctx->inode_link_info);
3257 if (pctx.errcode) {
3258 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
3259 ctx->flags |= E2F_FLAG_ABORT;
3260 return;
3262 inode_size = EXT2_INODE_SIZE(fs->super);
3263 inode = (struct ext2_inode *)
3264 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
3266 inodes_to_process = (struct process_inode_block *)
3267 e2fsck_allocate_memory(ctx,
3268 (ctx->process_inode_size *
3269 sizeof(struct process_inode_block)),
3270 "array of inodes to process");
3271 process_inode_count = 0;
3273 pctx.errcode = ext2fs_init_dblist(fs, 0);
3274 if (pctx.errcode) {
3275 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
3276 ctx->flags |= E2F_FLAG_ABORT;
3277 return;
3281 * If the last orphan field is set, clear it, since the pass1
3282 * processing will automatically find and clear the orphans.
3283 * In the future, we may want to try using the last_orphan
3284 * linked list ourselves, but for now, we clear it so that the
3285 * ext3 mount code won't get confused.
3287 if (!(ctx->options & E2F_OPT_READONLY)) {
3288 if (fs->super->s_last_orphan) {
3289 fs->super->s_last_orphan = 0;
3290 ext2fs_mark_super_dirty(fs);
3294 mark_table_blocks(ctx);
3295 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
3296 "block interate buffer");
3297 e2fsck_use_inode_shortcuts(ctx, 1);
3298 ehandler_operation(_("doing inode scan"));
3299 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
3300 &scan);
3301 if (pctx.errcode) {
3302 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3303 ctx->flags |= E2F_FLAG_ABORT;
3304 return;
3306 ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
3307 ctx->stashed_inode = inode;
3308 scan_struct.ctx = ctx;
3309 scan_struct.block_buf = block_buf;
3310 ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
3311 if (ctx->progress)
3312 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
3313 return;
3314 if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
3315 (fs->super->s_mtime < fs->super->s_inodes_count))
3316 busted_fs_time = 1;
3318 while (1) {
3319 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
3320 inode, inode_size);
3321 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3322 return;
3323 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
3324 continue;
3326 if (pctx.errcode) {
3327 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3328 ctx->flags |= E2F_FLAG_ABORT;
3329 return;
3331 if (!ino)
3332 break;
3333 pctx.ino = ino;
3334 pctx.inode = inode;
3335 ctx->stashed_ino = ino;
3336 if (inode->i_links_count) {
3337 pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
3338 ino, inode->i_links_count);
3339 if (pctx.errcode) {
3340 pctx.num = inode->i_links_count;
3341 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
3342 ctx->flags |= E2F_FLAG_ABORT;
3343 return;
3346 if (ino == EXT2_BAD_INO) {
3347 struct process_block_struct_1 pb;
3349 pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
3350 &pb.fs_meta_blocks);
3351 if (pctx.errcode) {
3352 pctx.num = 4;
3353 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3354 ctx->flags |= E2F_FLAG_ABORT;
3355 return;
3357 pb.ino = EXT2_BAD_INO;
3358 pb.num_blocks = pb.last_block = 0;
3359 pb.num_illegal_blocks = 0;
3360 pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
3361 pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
3362 pb.inode = inode;
3363 pb.pctx = &pctx;
3364 pb.ctx = ctx;
3365 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
3366 block_buf, process_bad_block, &pb);
3367 ext2fs_free_block_bitmap(pb.fs_meta_blocks);
3368 if (pctx.errcode) {
3369 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
3370 ctx->flags |= E2F_FLAG_ABORT;
3371 return;
3373 if (pb.bbcheck)
3374 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
3375 ctx->flags |= E2F_FLAG_ABORT;
3376 return;
3378 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3379 clear_problem_context(&pctx);
3380 continue;
3381 } else if (ino == EXT2_ROOT_INO) {
3383 * Make sure the root inode is a directory; if
3384 * not, offer to clear it. It will be
3385 * regnerated in pass #3.
3387 if (!LINUX_S_ISDIR(inode->i_mode)) {
3388 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
3389 inode->i_dtime = time(NULL);
3390 inode->i_links_count = 0;
3391 ext2fs_icount_store(ctx->inode_link_info,
3392 ino, 0);
3393 e2fsck_write_inode(ctx, ino, inode,
3394 "pass1");
3398 * If dtime is set, offer to clear it. mke2fs
3399 * version 0.2b created filesystems with the
3400 * dtime field set for the root and lost+found
3401 * directories. We won't worry about
3402 * /lost+found, since that can be regenerated
3403 * easily. But we will fix the root directory
3404 * as a special case.
3406 if (inode->i_dtime && inode->i_links_count) {
3407 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
3408 inode->i_dtime = 0;
3409 e2fsck_write_inode(ctx, ino, inode,
3410 "pass1");
3413 } else if (ino == EXT2_JOURNAL_INO) {
3414 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3415 if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
3416 if (!LINUX_S_ISREG(inode->i_mode) &&
3417 fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
3418 &pctx)) {
3419 inode->i_mode = LINUX_S_IFREG;
3420 e2fsck_write_inode(ctx, ino, inode,
3421 "pass1");
3423 check_blocks(ctx, &pctx, block_buf);
3424 continue;
3426 if ((inode->i_links_count || inode->i_blocks ||
3427 inode->i_blocks || inode->i_block[0]) &&
3428 fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
3429 &pctx)) {
3430 memset(inode, 0, inode_size);
3431 ext2fs_icount_store(ctx->inode_link_info,
3432 ino, 0);
3433 e2fsck_write_inode_full(ctx, ino, inode,
3434 inode_size, "pass1");
3436 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
3437 int problem = 0;
3439 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3440 if (ino == EXT2_BOOT_LOADER_INO) {
3441 if (LINUX_S_ISDIR(inode->i_mode))
3442 problem = PR_1_RESERVED_BAD_MODE;
3443 } else if (ino == EXT2_RESIZE_INO) {
3444 if (inode->i_mode &&
3445 !LINUX_S_ISREG(inode->i_mode))
3446 problem = PR_1_RESERVED_BAD_MODE;
3447 } else {
3448 if (inode->i_mode != 0)
3449 problem = PR_1_RESERVED_BAD_MODE;
3451 if (problem) {
3452 if (fix_problem(ctx, problem, &pctx)) {
3453 inode->i_mode = 0;
3454 e2fsck_write_inode(ctx, ino, inode,
3455 "pass1");
3458 check_blocks(ctx, &pctx, block_buf);
3459 continue;
3462 * Check for inodes who might have been part of the
3463 * orphaned list linked list. They should have gotten
3464 * dealt with by now, unless the list had somehow been
3465 * corrupted.
3467 * FIXME: In the future, inodes which are still in use
3468 * (and which are therefore) pending truncation should
3469 * be handled specially. Right now we just clear the
3470 * dtime field, and the normal e2fsck handling of
3471 * inodes where i_size and the inode blocks are
3472 * inconsistent is to fix i_size, instead of releasing
3473 * the extra blocks. This won't catch the inodes that
3474 * was at the end of the orphan list, but it's better
3475 * than nothing. The right answer is that there
3476 * shouldn't be any bugs in the orphan list handling. :-)
3478 if (inode->i_dtime && !busted_fs_time &&
3479 inode->i_dtime < ctx->fs->super->s_inodes_count) {
3480 if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
3481 inode->i_dtime = inode->i_links_count ?
3482 0 : time(NULL);
3483 e2fsck_write_inode(ctx, ino, inode,
3484 "pass1");
3489 * This code assumes that deleted inodes have
3490 * i_links_count set to 0.
3492 if (!inode->i_links_count) {
3493 if (!inode->i_dtime && inode->i_mode) {
3494 if (fix_problem(ctx,
3495 PR_1_ZERO_DTIME, &pctx)) {
3496 inode->i_dtime = time(NULL);
3497 e2fsck_write_inode(ctx, ino, inode,
3498 "pass1");
3501 continue;
3504 * n.b. 0.3c ext2fs code didn't clear i_links_count for
3505 * deleted files. Oops.
3507 * Since all new ext2 implementations get this right,
3508 * we now assume that the case of non-zero
3509 * i_links_count and non-zero dtime means that we
3510 * should keep the file, not delete it.
3513 if (inode->i_dtime) {
3514 if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
3515 inode->i_dtime = 0;
3516 e2fsck_write_inode(ctx, ino, inode, "pass1");
3520 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3521 switch (fs->super->s_creator_os) {
3522 case EXT2_OS_LINUX:
3523 frag = inode->osd2.linux2.l_i_frag;
3524 fsize = inode->osd2.linux2.l_i_fsize;
3525 break;
3526 case EXT2_OS_HURD:
3527 frag = inode->osd2.hurd2.h_i_frag;
3528 fsize = inode->osd2.hurd2.h_i_fsize;
3529 break;
3530 case EXT2_OS_MASIX:
3531 frag = inode->osd2.masix2.m_i_frag;
3532 fsize = inode->osd2.masix2.m_i_fsize;
3533 break;
3534 default:
3535 frag = fsize = 0;
3538 if (inode->i_faddr || frag || fsize ||
3539 (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
3540 mark_inode_bad(ctx, ino);
3541 if (inode->i_flags & EXT2_IMAGIC_FL) {
3542 if (imagic_fs) {
3543 if (!ctx->inode_imagic_map)
3544 alloc_imagic_map(ctx);
3545 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
3546 ino);
3547 } else {
3548 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
3549 inode->i_flags &= ~EXT2_IMAGIC_FL;
3550 e2fsck_write_inode(ctx, ino,
3551 inode, "pass1");
3556 check_inode_extra_space(ctx, &pctx);
3558 if (LINUX_S_ISDIR(inode->i_mode)) {
3559 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
3560 e2fsck_add_dir_info(ctx, ino, 0);
3561 ctx->fs_directory_count++;
3562 } else if (LINUX_S_ISREG (inode->i_mode)) {
3563 ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
3564 ctx->fs_regular_count++;
3565 } else if (LINUX_S_ISCHR (inode->i_mode) &&
3566 e2fsck_pass1_check_device_inode(fs, inode)) {
3567 check_immutable(ctx, &pctx);
3568 check_size(ctx, &pctx);
3569 ctx->fs_chardev_count++;
3570 } else if (LINUX_S_ISBLK (inode->i_mode) &&
3571 e2fsck_pass1_check_device_inode(fs, inode)) {
3572 check_immutable(ctx, &pctx);
3573 check_size(ctx, &pctx);
3574 ctx->fs_blockdev_count++;
3575 } else if (LINUX_S_ISLNK (inode->i_mode) &&
3576 e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
3577 check_immutable(ctx, &pctx);
3578 ctx->fs_symlinks_count++;
3579 if (ext2fs_inode_data_blocks(fs, inode) == 0) {
3580 ctx->fs_fast_symlinks_count++;
3581 check_blocks(ctx, &pctx, block_buf);
3582 continue;
3585 else if (LINUX_S_ISFIFO (inode->i_mode) &&
3586 e2fsck_pass1_check_device_inode(fs, inode)) {
3587 check_immutable(ctx, &pctx);
3588 check_size(ctx, &pctx);
3589 ctx->fs_fifo_count++;
3590 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
3591 e2fsck_pass1_check_device_inode(fs, inode)) {
3592 check_immutable(ctx, &pctx);
3593 check_size(ctx, &pctx);
3594 ctx->fs_sockets_count++;
3595 } else
3596 mark_inode_bad(ctx, ino);
3597 if (inode->i_block[EXT2_IND_BLOCK])
3598 ctx->fs_ind_count++;
3599 if (inode->i_block[EXT2_DIND_BLOCK])
3600 ctx->fs_dind_count++;
3601 if (inode->i_block[EXT2_TIND_BLOCK])
3602 ctx->fs_tind_count++;
3603 if (inode->i_block[EXT2_IND_BLOCK] ||
3604 inode->i_block[EXT2_DIND_BLOCK] ||
3605 inode->i_block[EXT2_TIND_BLOCK] ||
3606 inode->i_file_acl) {
3607 inodes_to_process[process_inode_count].ino = ino;
3608 inodes_to_process[process_inode_count].inode = *inode;
3609 process_inode_count++;
3610 } else
3611 check_blocks(ctx, &pctx, block_buf);
3613 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3614 return;
3616 if (process_inode_count >= ctx->process_inode_size) {
3617 process_inodes(ctx, block_buf);
3619 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3620 return;
3623 process_inodes(ctx, block_buf);
3624 ext2fs_close_inode_scan(scan);
3625 ehandler_operation(0);
3628 * If any extended attribute blocks' reference counts need to
3629 * be adjusted, either up (ctx->refcount_extra), or down
3630 * (ctx->refcount), then fix them.
3632 if (ctx->refcount) {
3633 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
3634 ea_refcount_free(ctx->refcount);
3635 ctx->refcount = 0;
3637 if (ctx->refcount_extra) {
3638 adjust_extattr_refcount(ctx, ctx->refcount_extra,
3639 block_buf, +1);
3640 ea_refcount_free(ctx->refcount_extra);
3641 ctx->refcount_extra = 0;
3644 if (ctx->invalid_bitmaps)
3645 handle_fs_bad_blocks(ctx);
3647 /* We don't need the block_ea_map any more */
3648 ext2fs_free_block_bitmap(ctx->block_ea_map);
3649 ctx->block_ea_map = 0;
3651 if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
3652 ext2fs_block_bitmap save_bmap;
3654 save_bmap = fs->block_map;
3655 fs->block_map = ctx->block_found_map;
3656 clear_problem_context(&pctx);
3657 pctx.errcode = ext2fs_create_resize_inode(fs);
3658 if (pctx.errcode) {
3659 fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
3660 /* Should never get here */
3661 ctx->flags |= E2F_FLAG_ABORT;
3662 return;
3664 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
3665 "recreate inode");
3666 inode->i_mtime = time(NULL);
3667 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
3668 "recreate inode");
3669 fs->block_map = save_bmap;
3670 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
3673 if (ctx->flags & E2F_FLAG_RESTART) {
3675 * Only the master copy of the superblock and block
3676 * group descriptors are going to be written during a
3677 * restart, so set the superblock to be used to be the
3678 * master superblock.
3680 ctx->use_superblock = 0;
3681 unwind_pass1();
3682 goto endit;
3685 if (ctx->block_dup_map) {
3686 if (ctx->options & E2F_OPT_PREEN) {
3687 clear_problem_context(&pctx);
3688 fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
3690 e2fsck_pass1_dupblocks(ctx, block_buf);
3692 ext2fs_free_mem(&inodes_to_process);
3693 endit:
3694 e2fsck_use_inode_shortcuts(ctx, 0);
3696 ext2fs_free_mem(&block_buf);
3697 ext2fs_free_mem(&inode);
3701 * When the inode_scan routines call this callback at the end of the
3702 * glock group, call process_inodes.
3704 static errcode_t scan_callback(ext2_filsys fs,
3705 dgrp_t group, void * priv_data)
3707 struct scan_callback_struct *scan_struct;
3708 e2fsck_t ctx;
3710 scan_struct = (struct scan_callback_struct *) priv_data;
3711 ctx = scan_struct->ctx;
3713 process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
3715 if (ctx->progress)
3716 if ((ctx->progress)(ctx, 1, group+1,
3717 ctx->fs->group_desc_count))
3718 return EXT2_ET_CANCEL_REQUESTED;
3720 return 0;
3724 * Process the inodes in the "inodes to process" list.
3726 static void process_inodes(e2fsck_t ctx, char *block_buf)
3728 int i;
3729 struct ext2_inode *old_stashed_inode;
3730 ext2_ino_t old_stashed_ino;
3731 const char *old_operation;
3732 char buf[80];
3733 struct problem_context pctx;
3735 /* begin process_inodes */
3736 if (process_inode_count == 0)
3737 return;
3738 old_operation = ehandler_operation(0);
3739 old_stashed_inode = ctx->stashed_inode;
3740 old_stashed_ino = ctx->stashed_ino;
3741 qsort(inodes_to_process, process_inode_count,
3742 sizeof(struct process_inode_block), process_inode_cmp);
3743 clear_problem_context(&pctx);
3744 for (i=0; i < process_inode_count; i++) {
3745 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
3746 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
3747 sprintf(buf, _("reading indirect blocks of inode %u"),
3748 pctx.ino);
3749 ehandler_operation(buf);
3750 check_blocks(ctx, &pctx, block_buf);
3751 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3752 break;
3754 ctx->stashed_inode = old_stashed_inode;
3755 ctx->stashed_ino = old_stashed_ino;
3756 process_inode_count = 0;
3757 /* end process inodes */
3759 ehandler_operation(old_operation);
3762 static int process_inode_cmp(const void *a, const void *b)
3764 const struct process_inode_block *ib_a =
3765 (const struct process_inode_block *) a;
3766 const struct process_inode_block *ib_b =
3767 (const struct process_inode_block *) b;
3768 int ret;
3770 ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
3771 ib_b->inode.i_block[EXT2_IND_BLOCK]);
3772 if (ret == 0)
3773 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
3774 return ret;
3778 * Mark an inode as being bad in some what
3780 static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
3782 struct problem_context pctx;
3784 if (!ctx->inode_bad_map) {
3785 clear_problem_context(&pctx);
3787 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3788 _("bad inode map"), &ctx->inode_bad_map);
3789 if (pctx.errcode) {
3790 pctx.num = 3;
3791 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3792 /* Should never get here */
3793 ctx->flags |= E2F_FLAG_ABORT;
3794 return;
3797 ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
3802 * This procedure will allocate the inode imagic table
3804 static void alloc_imagic_map(e2fsck_t ctx)
3806 struct problem_context pctx;
3808 clear_problem_context(&pctx);
3809 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3810 _("imagic inode map"),
3811 &ctx->inode_imagic_map);
3812 if (pctx.errcode) {
3813 pctx.num = 5;
3814 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3815 /* Should never get here */
3816 ctx->flags |= E2F_FLAG_ABORT;
3817 return;
3822 * Marks a block as in use, setting the dup_map if it's been set
3823 * already. Called by process_block and process_bad_block.
3825 * WARNING: Assumes checks have already been done to make sure block
3826 * is valid. This is true in both process_block and process_bad_block.
3828 static void mark_block_used(e2fsck_t ctx, blk_t block)
3830 struct problem_context pctx;
3832 clear_problem_context(&pctx);
3834 if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
3835 if (!ctx->block_dup_map) {
3836 pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
3837 _("multiply claimed block map"),
3838 &ctx->block_dup_map);
3839 if (pctx.errcode) {
3840 pctx.num = 3;
3841 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
3842 &pctx);
3843 /* Should never get here */
3844 ctx->flags |= E2F_FLAG_ABORT;
3845 return;
3848 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
3849 } else {
3850 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
3855 * Adjust the extended attribute block's reference counts at the end
3856 * of pass 1, either by subtracting out references for EA blocks that
3857 * are still referenced in ctx->refcount, or by adding references for
3858 * EA blocks that had extra references as accounted for in
3859 * ctx->refcount_extra.
3861 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3862 char *block_buf, int adjust_sign)
3864 struct ext2_ext_attr_header *header;
3865 struct problem_context pctx;
3866 ext2_filsys fs = ctx->fs;
3867 blk_t blk;
3868 __u32 should_be;
3869 int count;
3871 clear_problem_context(&pctx);
3873 ea_refcount_intr_begin(refcount);
3874 while (1) {
3875 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
3876 break;
3877 pctx.blk = blk;
3878 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3879 if (pctx.errcode) {
3880 fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
3881 return;
3883 header = (struct ext2_ext_attr_header *) block_buf;
3884 pctx.blkcount = header->h_refcount;
3885 should_be = header->h_refcount + adjust_sign * count;
3886 pctx.num = should_be;
3887 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
3888 header->h_refcount = should_be;
3889 pctx.errcode = ext2fs_write_ext_attr(fs, blk,
3890 block_buf);
3891 if (pctx.errcode) {
3892 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
3893 continue;
3900 * Handle processing the extended attribute blocks
3902 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
3903 char *block_buf)
3905 ext2_filsys fs = ctx->fs;
3906 ext2_ino_t ino = pctx->ino;
3907 struct ext2_inode *inode = pctx->inode;
3908 blk_t blk;
3909 char * end;
3910 struct ext2_ext_attr_header *header;
3911 struct ext2_ext_attr_entry *entry;
3912 int count;
3913 region_t region;
3915 blk = inode->i_file_acl;
3916 if (blk == 0)
3917 return 0;
3920 * If the Extended attribute flag isn't set, then a non-zero
3921 * file acl means that the inode is corrupted.
3923 * Or if the extended attribute block is an invalid block,
3924 * then the inode is also corrupted.
3926 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
3927 (blk < fs->super->s_first_data_block) ||
3928 (blk >= fs->super->s_blocks_count)) {
3929 mark_inode_bad(ctx, ino);
3930 return 0;
3933 /* If ea bitmap hasn't been allocated, create it */
3934 if (!ctx->block_ea_map) {
3935 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
3936 _("ext attr block map"),
3937 &ctx->block_ea_map);
3938 if (pctx->errcode) {
3939 pctx->num = 2;
3940 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
3941 ctx->flags |= E2F_FLAG_ABORT;
3942 return 0;
3946 /* Create the EA refcount structure if necessary */
3947 if (!ctx->refcount) {
3948 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
3949 if (pctx->errcode) {
3950 pctx->num = 1;
3951 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3952 ctx->flags |= E2F_FLAG_ABORT;
3953 return 0;
3957 /* Have we seen this EA block before? */
3958 if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
3959 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
3960 return 1;
3961 /* Ooops, this EA was referenced more than it stated */
3962 if (!ctx->refcount_extra) {
3963 pctx->errcode = ea_refcount_create(0,
3964 &ctx->refcount_extra);
3965 if (pctx->errcode) {
3966 pctx->num = 2;
3967 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3968 ctx->flags |= E2F_FLAG_ABORT;
3969 return 0;
3972 ea_refcount_increment(ctx->refcount_extra, blk, 0);
3973 return 1;
3977 * OK, we haven't seen this EA block yet. So we need to
3978 * validate it
3980 pctx->blk = blk;
3981 pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3982 if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
3983 goto clear_extattr;
3984 header = (struct ext2_ext_attr_header *) block_buf;
3985 pctx->blk = inode->i_file_acl;
3986 if (((ctx->ext_attr_ver == 1) &&
3987 (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
3988 ((ctx->ext_attr_ver == 2) &&
3989 (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
3990 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
3991 goto clear_extattr;
3994 if (header->h_blocks != 1) {
3995 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
3996 goto clear_extattr;
3999 region = region_create(0, fs->blocksize);
4000 if (!region) {
4001 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
4002 ctx->flags |= E2F_FLAG_ABORT;
4003 return 0;
4005 if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
4006 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4007 goto clear_extattr;
4010 entry = (struct ext2_ext_attr_entry *)(header+1);
4011 end = block_buf + fs->blocksize;
4012 while ((char *)entry < end && *(__u32 *)entry) {
4013 if (region_allocate(region, (char *)entry - (char *)header,
4014 EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
4015 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4016 goto clear_extattr;
4018 if ((ctx->ext_attr_ver == 1 &&
4019 (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
4020 (ctx->ext_attr_ver == 2 &&
4021 entry->e_name_index == 0)) {
4022 if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
4023 goto clear_extattr;
4025 if (entry->e_value_block != 0) {
4026 if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
4027 goto clear_extattr;
4029 if (entry->e_value_size &&
4030 region_allocate(region, entry->e_value_offs,
4031 EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
4032 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4033 goto clear_extattr;
4035 entry = EXT2_EXT_ATTR_NEXT(entry);
4037 if (region_allocate(region, (char *)entry - (char *)header, 4)) {
4038 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4039 goto clear_extattr;
4041 region_free(region);
4043 count = header->h_refcount - 1;
4044 if (count)
4045 ea_refcount_store(ctx->refcount, blk, count);
4046 mark_block_used(ctx, blk);
4047 ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
4049 return 1;
4051 clear_extattr:
4052 inode->i_file_acl = 0;
4053 e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
4054 return 0;
4057 /* Returns 1 if bad htree, 0 if OK */
4058 static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
4059 ext2_ino_t ino FSCK_ATTR((unused)),
4060 struct ext2_inode *inode,
4061 char *block_buf)
4063 struct ext2_dx_root_info *root;
4064 ext2_filsys fs = ctx->fs;
4065 errcode_t retval;
4066 blk_t blk;
4068 if ((!LINUX_S_ISDIR(inode->i_mode) &&
4069 fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
4070 (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4071 fix_problem(ctx, PR_1_HTREE_SET, pctx)))
4072 return 1;
4074 blk = inode->i_block[0];
4075 if (((blk == 0) ||
4076 (blk < fs->super->s_first_data_block) ||
4077 (blk >= fs->super->s_blocks_count)) &&
4078 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4079 return 1;
4081 retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
4082 if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4083 return 1;
4085 /* XXX should check that beginning matches a directory */
4086 root = (struct ext2_dx_root_info *) (block_buf + 24);
4088 if ((root->reserved_zero || root->info_length < 8) &&
4089 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4090 return 1;
4092 pctx->num = root->hash_version;
4093 if ((root->hash_version != EXT2_HASH_LEGACY) &&
4094 (root->hash_version != EXT2_HASH_HALF_MD4) &&
4095 (root->hash_version != EXT2_HASH_TEA) &&
4096 fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
4097 return 1;
4099 if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
4100 fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
4101 return 1;
4103 pctx->num = root->indirect_levels;
4104 if ((root->indirect_levels > 1) &&
4105 fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
4106 return 1;
4108 return 0;
4112 * This subroutine is called on each inode to account for all of the
4113 * blocks used by that inode.
4115 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4116 char *block_buf)
4118 ext2_filsys fs = ctx->fs;
4119 struct process_block_struct_1 pb;
4120 ext2_ino_t ino = pctx->ino;
4121 struct ext2_inode *inode = pctx->inode;
4122 int bad_size = 0;
4123 int dirty_inode = 0;
4124 __u64 size;
4126 pb.ino = ino;
4127 pb.num_blocks = 0;
4128 pb.last_block = -1;
4129 pb.num_illegal_blocks = 0;
4130 pb.suppress = 0; pb.clear = 0;
4131 pb.fragmented = 0;
4132 pb.compressed = 0;
4133 pb.previous_block = 0;
4134 pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
4135 pb.is_reg = LINUX_S_ISREG(inode->i_mode);
4136 pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
4137 pb.inode = inode;
4138 pb.pctx = pctx;
4139 pb.ctx = ctx;
4140 pctx->ino = ino;
4141 pctx->errcode = 0;
4143 if (inode->i_flags & EXT2_COMPRBLK_FL) {
4144 if (fs->super->s_feature_incompat &
4145 EXT2_FEATURE_INCOMPAT_COMPRESSION)
4146 pb.compressed = 1;
4147 else {
4148 if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
4149 inode->i_flags &= ~EXT2_COMPRBLK_FL;
4150 dirty_inode++;
4155 if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
4156 pb.num_blocks++;
4158 if (ext2fs_inode_has_valid_blocks(inode))
4159 pctx->errcode = ext2fs_block_iterate2(fs, ino,
4160 pb.is_dir ? BLOCK_FLAG_HOLE : 0,
4161 block_buf, process_block, &pb);
4162 end_problem_latch(ctx, PR_LATCH_BLOCK);
4163 end_problem_latch(ctx, PR_LATCH_TOOBIG);
4164 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4165 goto out;
4166 if (pctx->errcode)
4167 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
4169 if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
4170 ctx->fs_fragmented++;
4172 if (pb.clear) {
4173 inode->i_links_count = 0;
4174 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4175 inode->i_dtime = time(NULL);
4176 dirty_inode++;
4177 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4178 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4179 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4181 * The inode was probably partially accounted for
4182 * before processing was aborted, so we need to
4183 * restart the pass 1 scan.
4185 ctx->flags |= E2F_FLAG_RESTART;
4186 goto out;
4189 if (inode->i_flags & EXT2_INDEX_FL) {
4190 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
4191 inode->i_flags &= ~EXT2_INDEX_FL;
4192 dirty_inode++;
4193 } else {
4194 #ifdef ENABLE_HTREE
4195 e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
4196 #endif
4199 if (ctx->dirs_to_hash && pb.is_dir &&
4200 !(inode->i_flags & EXT2_INDEX_FL) &&
4201 ((inode->i_size / fs->blocksize) >= 3))
4202 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
4204 if (!pb.num_blocks && pb.is_dir) {
4205 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
4206 inode->i_links_count = 0;
4207 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4208 inode->i_dtime = time(NULL);
4209 dirty_inode++;
4210 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4211 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4212 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4213 ctx->fs_directory_count--;
4214 goto out;
4218 pb.num_blocks *= (fs->blocksize / 512);
4220 if (pb.is_dir) {
4221 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
4222 if (nblock > (pb.last_block + 1))
4223 bad_size = 1;
4224 else if (nblock < (pb.last_block + 1)) {
4225 if (((pb.last_block + 1) - nblock) >
4226 fs->super->s_prealloc_dir_blocks)
4227 bad_size = 2;
4229 } else {
4230 size = EXT2_I_SIZE(inode);
4231 if ((pb.last_block >= 0) &&
4232 (size < (__u64) pb.last_block * fs->blocksize))
4233 bad_size = 3;
4234 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
4235 bad_size = 4;
4237 /* i_size for symlinks is checked elsewhere */
4238 if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
4239 pctx->num = (pb.last_block+1) * fs->blocksize;
4240 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
4241 inode->i_size = pctx->num;
4242 if (!LINUX_S_ISDIR(inode->i_mode))
4243 inode->i_size_high = pctx->num >> 32;
4244 dirty_inode++;
4246 pctx->num = 0;
4248 if (LINUX_S_ISREG(inode->i_mode) &&
4249 (inode->i_size_high || inode->i_size & 0x80000000UL))
4250 ctx->large_files++;
4251 if (pb.num_blocks != inode->i_blocks) {
4252 pctx->num = pb.num_blocks;
4253 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
4254 inode->i_blocks = pb.num_blocks;
4255 dirty_inode++;
4257 pctx->num = 0;
4259 out:
4260 if (dirty_inode)
4261 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
4266 * This is a helper function for check_blocks().
4268 static int process_block(ext2_filsys fs,
4269 blk_t *block_nr,
4270 e2_blkcnt_t blockcnt,
4271 blk_t ref_block FSCK_ATTR((unused)),
4272 int ref_offset FSCK_ATTR((unused)),
4273 void *priv_data)
4275 struct process_block_struct_1 *p;
4276 struct problem_context *pctx;
4277 blk_t blk = *block_nr;
4278 int ret_code = 0;
4279 int problem = 0;
4280 e2fsck_t ctx;
4282 p = (struct process_block_struct_1 *) priv_data;
4283 pctx = p->pctx;
4284 ctx = p->ctx;
4286 if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
4287 /* todo: Check that the comprblk_fl is high, that the
4288 blkaddr pattern looks right (all non-holes up to
4289 first EXT2FS_COMPRESSED_BLKADDR, then all
4290 EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
4291 that the feature_incompat bit is high, and that the
4292 inode is a regular file. If we're doing a "full
4293 check" (a concept introduced to e2fsck by e2compr,
4294 meaning that we look at data blocks as well as
4295 metadata) then call some library routine that
4296 checks the compressed data. I'll have to think
4297 about this, because one particularly important
4298 problem to be able to fix is to recalculate the
4299 cluster size if necessary. I think that perhaps
4300 we'd better do most/all e2compr-specific checks
4301 separately, after the non-e2compr checks. If not
4302 doing a full check, it may be useful to test that
4303 the personality is linux; e.g. if it isn't then
4304 perhaps this really is just an illegal block. */
4305 return 0;
4308 if (blk == 0) {
4309 if (p->is_dir == 0) {
4311 * Should never happen, since only directories
4312 * get called with BLOCK_FLAG_HOLE
4314 #ifdef DEBUG_E2FSCK
4315 printf("process_block() called with blk == 0, "
4316 "blockcnt=%d, inode %lu???\n",
4317 blockcnt, p->ino);
4318 #endif
4319 return 0;
4321 if (blockcnt < 0)
4322 return 0;
4323 if (blockcnt * fs->blocksize < p->inode->i_size) {
4324 goto mark_dir;
4326 return 0;
4330 * Simplistic fragmentation check. We merely require that the
4331 * file be contiguous. (Which can never be true for really
4332 * big files that are greater than a block group.)
4334 if (!HOLE_BLKADDR(p->previous_block)) {
4335 if (p->previous_block+1 != blk)
4336 p->fragmented = 1;
4338 p->previous_block = blk;
4340 if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
4341 problem = PR_1_TOOBIG_DIR;
4342 if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
4343 problem = PR_1_TOOBIG_REG;
4344 if (!p->is_dir && !p->is_reg && blockcnt > 0)
4345 problem = PR_1_TOOBIG_SYMLINK;
4347 if (blk < fs->super->s_first_data_block ||
4348 blk >= fs->super->s_blocks_count)
4349 problem = PR_1_ILLEGAL_BLOCK_NUM;
4351 if (problem) {
4352 p->num_illegal_blocks++;
4353 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
4354 if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
4355 p->clear = 1;
4356 return BLOCK_ABORT;
4358 if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
4359 p->suppress = 1;
4360 set_latch_flags(PR_LATCH_BLOCK,
4361 PRL_SUPPRESS, 0);
4364 pctx->blk = blk;
4365 pctx->blkcount = blockcnt;
4366 if (fix_problem(ctx, problem, pctx)) {
4367 blk = *block_nr = 0;
4368 ret_code = BLOCK_CHANGED;
4369 goto mark_dir;
4370 } else
4371 return 0;
4374 if (p->ino == EXT2_RESIZE_INO) {
4376 * The resize inode has already be sanity checked
4377 * during pass #0 (the superblock checks). All we
4378 * have to do is mark the double indirect block as
4379 * being in use; all of the other blocks are handled
4380 * by mark_table_blocks()).
4382 if (blockcnt == BLOCK_COUNT_DIND)
4383 mark_block_used(ctx, blk);
4384 } else
4385 mark_block_used(ctx, blk);
4386 p->num_blocks++;
4387 if (blockcnt >= 0)
4388 p->last_block = blockcnt;
4389 mark_dir:
4390 if (p->is_dir && (blockcnt >= 0)) {
4391 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
4392 blk, blockcnt);
4393 if (pctx->errcode) {
4394 pctx->blk = blk;
4395 pctx->num = blockcnt;
4396 fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
4397 /* Should never get here */
4398 ctx->flags |= E2F_FLAG_ABORT;
4399 return BLOCK_ABORT;
4402 return ret_code;
4405 static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
4406 blk_t *block_nr,
4407 e2_blkcnt_t blockcnt,
4408 blk_t ref_block FSCK_ATTR((unused)),
4409 int ref_offset FSCK_ATTR((unused)),
4410 void *priv_data EXT2FS_ATTR((unused)))
4413 * Note: This function processes blocks for the bad blocks
4414 * inode, which is never compressed. So we don't use HOLE_BLKADDR().
4417 printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
4418 return BLOCK_ERROR;
4422 * This routine gets called at the end of pass 1 if bad blocks are
4423 * detected in the superblock, group descriptors, inode_bitmaps, or
4424 * block bitmaps. At this point, all of the blocks have been mapped
4425 * out, so we can try to allocate new block(s) to replace the bad
4426 * blocks.
4428 static void handle_fs_bad_blocks(e2fsck_t ctx EXT2FS_ATTR((unused)))
4430 printf("Bad blocks detected on your filesystem\n"
4431 "You should get your data off as the device will soon die\n");
4435 * This routine marks all blocks which are used by the superblock,
4436 * group descriptors, inode bitmaps, and block bitmaps.
4438 static void mark_table_blocks(e2fsck_t ctx)
4440 ext2_filsys fs = ctx->fs;
4441 blk_t block, b;
4442 dgrp_t i;
4443 int j;
4444 struct problem_context pctx;
4446 clear_problem_context(&pctx);
4448 block = fs->super->s_first_data_block;
4449 for (i = 0; i < fs->group_desc_count; i++) {
4450 pctx.group = i;
4452 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
4455 * Mark the blocks used for the inode table
4457 if (fs->group_desc[i].bg_inode_table) {
4458 for (j = 0, b = fs->group_desc[i].bg_inode_table;
4459 j < fs->inode_blocks_per_group;
4460 j++, b++) {
4461 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4462 b)) {
4463 pctx.blk = b;
4464 if (fix_problem(ctx,
4465 PR_1_ITABLE_CONFLICT, &pctx)) {
4466 ctx->invalid_inode_table_flag[i]++;
4467 ctx->invalid_bitmaps++;
4469 } else {
4470 ext2fs_mark_block_bitmap(ctx->block_found_map, b);
4476 * Mark block used for the block bitmap
4478 if (fs->group_desc[i].bg_block_bitmap) {
4479 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4480 fs->group_desc[i].bg_block_bitmap)) {
4481 pctx.blk = fs->group_desc[i].bg_block_bitmap;
4482 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
4483 ctx->invalid_block_bitmap_flag[i]++;
4484 ctx->invalid_bitmaps++;
4486 } else {
4487 ext2fs_mark_block_bitmap(ctx->block_found_map,
4488 fs->group_desc[i].bg_block_bitmap);
4492 * Mark block used for the inode bitmap
4494 if (fs->group_desc[i].bg_inode_bitmap) {
4495 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4496 fs->group_desc[i].bg_inode_bitmap)) {
4497 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
4498 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
4499 ctx->invalid_inode_bitmap_flag[i]++;
4500 ctx->invalid_bitmaps++;
4502 } else {
4503 ext2fs_mark_block_bitmap(ctx->block_found_map,
4504 fs->group_desc[i].bg_inode_bitmap);
4507 block += fs->super->s_blocks_per_group;
4512 * Thes subroutines short circuits ext2fs_get_blocks and
4513 * ext2fs_check_directory; we use them since we already have the inode
4514 * structure, so there's no point in letting the ext2fs library read
4515 * the inode again.
4517 static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
4518 blk_t *blocks)
4520 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4521 int i;
4523 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4524 return EXT2_ET_CALLBACK_NOTHANDLED;
4526 for (i=0; i < EXT2_N_BLOCKS; i++)
4527 blocks[i] = ctx->stashed_inode->i_block[i];
4528 return 0;
4531 static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
4532 struct ext2_inode *inode)
4534 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4536 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4537 return EXT2_ET_CALLBACK_NOTHANDLED;
4538 *inode = *ctx->stashed_inode;
4539 return 0;
4542 static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
4543 struct ext2_inode *inode)
4545 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4547 if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
4548 *ctx->stashed_inode = *inode;
4549 return EXT2_ET_CALLBACK_NOTHANDLED;
4552 static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
4554 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4556 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4557 return EXT2_ET_CALLBACK_NOTHANDLED;
4559 if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
4560 return EXT2_ET_NO_DIRECTORY;
4561 return 0;
4564 void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int fl_bool)
4566 ext2_filsys fs = ctx->fs;
4568 if (fl_bool) {
4569 fs->get_blocks = pass1_get_blocks;
4570 fs->check_directory = pass1_check_directory;
4571 fs->read_inode = pass1_read_inode;
4572 fs->write_inode = pass1_write_inode;
4573 ctx->stashed_ino = 0;
4574 } else {
4575 fs->get_blocks = 0;
4576 fs->check_directory = 0;
4577 fs->read_inode = 0;
4578 fs->write_inode = 0;
4583 * pass1b.c --- Pass #1b of e2fsck
4585 * This file contains pass1B, pass1C, and pass1D of e2fsck. They are
4586 * only invoked if pass 1 discovered blocks which are in use by more
4587 * than one inode.
4589 * Pass1B scans the data blocks of all the inodes again, generating a
4590 * complete list of duplicate blocks and which inodes have claimed
4591 * them.
4593 * Pass1C does a tree-traversal of the filesystem, to determine the
4594 * parent directories of these inodes. This step is necessary so that
4595 * e2fsck can print out the pathnames of affected inodes.
4597 * Pass1D is a reconciliation pass. For each inode with duplicate
4598 * blocks, the user is prompted if s/he would like to clone the file
4599 * (so that the file gets a fresh copy of the duplicated blocks) or
4600 * simply to delete the file.
4605 /* Needed for architectures where sizeof(int) != sizeof(void *) */
4606 #define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val))
4607 #define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr))
4609 /* Define an extension to the ext2 library's block count information */
4610 #define BLOCK_COUNT_EXTATTR (-5)
4612 struct block_el {
4613 blk_t block;
4614 struct block_el *next;
4617 struct inode_el {
4618 ext2_ino_t inode;
4619 struct inode_el *next;
4622 struct dup_block {
4623 int num_bad;
4624 struct inode_el *inode_list;
4628 * This structure stores information about a particular inode which
4629 * is sharing blocks with other inodes. This information is collected
4630 * to display to the user, so that the user knows what files he or she
4631 * is dealing with, when trying to decide how to resolve the conflict
4632 * of multiply-claimed blocks.
4634 struct dup_inode {
4635 ext2_ino_t dir;
4636 int num_dupblocks;
4637 struct ext2_inode inode;
4638 struct block_el *block_list;
4641 static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
4642 e2_blkcnt_t blockcnt, blk_t ref_blk,
4643 int ref_offset, void *priv_data);
4644 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
4645 struct dup_inode *dp, char *block_buf);
4646 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
4647 struct dup_inode *dp, char* block_buf);
4648 static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
4650 static void pass1b(e2fsck_t ctx, char *block_buf);
4651 static void pass1c(e2fsck_t ctx, char *block_buf);
4652 static void pass1d(e2fsck_t ctx, char *block_buf);
4654 static int dup_inode_count = 0;
4656 static dict_t blk_dict, ino_dict;
4658 static ext2fs_inode_bitmap inode_dup_map;
4660 static int dict_int_cmp(const void *a, const void *b)
4662 intptr_t ia, ib;
4664 ia = (intptr_t)a;
4665 ib = (intptr_t)b;
4667 return (ia-ib);
4671 * Add a duplicate block record
4673 static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
4674 struct ext2_inode *inode)
4676 dnode_t *n;
4677 struct dup_block *db;
4678 struct dup_inode *di;
4679 struct block_el *blk_el;
4680 struct inode_el *ino_el;
4682 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
4683 if (n)
4684 db = (struct dup_block *) dnode_get(n);
4685 else {
4686 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
4687 sizeof(struct dup_block), "duplicate block header");
4688 db->num_bad = 0;
4689 db->inode_list = 0;
4690 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
4692 ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
4693 sizeof(struct inode_el), "inode element");
4694 ino_el->inode = ino;
4695 ino_el->next = db->inode_list;
4696 db->inode_list = ino_el;
4697 db->num_bad++;
4699 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
4700 if (n)
4701 di = (struct dup_inode *) dnode_get(n);
4702 else {
4703 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
4704 sizeof(struct dup_inode), "duplicate inode header");
4705 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0;
4706 di->num_dupblocks = 0;
4707 di->block_list = 0;
4708 di->inode = *inode;
4709 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
4711 blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
4712 sizeof(struct block_el), "block element");
4713 blk_el->block = blk;
4714 blk_el->next = di->block_list;
4715 di->block_list = blk_el;
4716 di->num_dupblocks++;
4720 * Free a duplicate inode record
4722 static void inode_dnode_free(dnode_t *node)
4724 struct dup_inode *di;
4725 struct block_el *p, *next;
4727 di = (struct dup_inode *) dnode_get(node);
4728 for (p = di->block_list; p; p = next) {
4729 next = p->next;
4730 free(p);
4732 free(node);
4736 * Free a duplicate block record
4738 static void block_dnode_free(dnode_t *node)
4740 struct dup_block *db;
4741 struct inode_el *p, *next;
4743 db = (struct dup_block *) dnode_get(node);
4744 for (p = db->inode_list; p; p = next) {
4745 next = p->next;
4746 free(p);
4748 free(node);
4753 * Main procedure for handling duplicate blocks
4755 void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
4757 ext2_filsys fs = ctx->fs;
4758 struct problem_context pctx;
4760 clear_problem_context(&pctx);
4762 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4763 _("multiply claimed inode map"), &inode_dup_map);
4764 if (pctx.errcode) {
4765 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
4766 ctx->flags |= E2F_FLAG_ABORT;
4767 return;
4770 dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4771 dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4772 dict_set_allocator(&ino_dict, inode_dnode_free);
4773 dict_set_allocator(&blk_dict, block_dnode_free);
4775 pass1b(ctx, block_buf);
4776 pass1c(ctx, block_buf);
4777 pass1d(ctx, block_buf);
4780 * Time to free all of the accumulated data structures that we
4781 * don't need anymore.
4783 dict_free_nodes(&ino_dict);
4784 dict_free_nodes(&blk_dict);
4788 * Scan the inodes looking for inodes that contain duplicate blocks.
4790 struct process_block_struct_1b {
4791 e2fsck_t ctx;
4792 ext2_ino_t ino;
4793 int dup_blocks;
4794 struct ext2_inode *inode;
4795 struct problem_context *pctx;
4798 static void pass1b(e2fsck_t ctx, char *block_buf)
4800 ext2_filsys fs = ctx->fs;
4801 ext2_ino_t ino;
4802 struct ext2_inode inode;
4803 ext2_inode_scan scan;
4804 struct process_block_struct_1b pb;
4805 struct problem_context pctx;
4807 clear_problem_context(&pctx);
4809 if (!(ctx->options & E2F_OPT_PREEN))
4810 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
4811 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4812 &scan);
4813 if (pctx.errcode) {
4814 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4815 ctx->flags |= E2F_FLAG_ABORT;
4816 return;
4818 ctx->stashed_inode = &inode;
4819 pb.ctx = ctx;
4820 pb.pctx = &pctx;
4821 pctx.str = "pass1b";
4822 while (1) {
4823 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
4824 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
4825 continue;
4826 if (pctx.errcode) {
4827 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4828 ctx->flags |= E2F_FLAG_ABORT;
4829 return;
4831 if (!ino)
4832 break;
4833 pctx.ino = ctx->stashed_ino = ino;
4834 if ((ino != EXT2_BAD_INO) &&
4835 !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
4836 continue;
4838 pb.ino = ino;
4839 pb.dup_blocks = 0;
4840 pb.inode = &inode;
4842 if (ext2fs_inode_has_valid_blocks(&inode) ||
4843 (ino == EXT2_BAD_INO))
4844 pctx.errcode = ext2fs_block_iterate2(fs, ino,
4845 0, block_buf, process_pass1b_block, &pb);
4846 if (inode.i_file_acl)
4847 process_pass1b_block(fs, &inode.i_file_acl,
4848 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
4849 if (pb.dup_blocks) {
4850 end_problem_latch(ctx, PR_LATCH_DBLOCK);
4851 if (ino >= EXT2_FIRST_INODE(fs->super) ||
4852 ino == EXT2_ROOT_INO)
4853 dup_inode_count++;
4855 if (pctx.errcode)
4856 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
4858 ext2fs_close_inode_scan(scan);
4859 e2fsck_use_inode_shortcuts(ctx, 0);
4862 static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
4863 blk_t *block_nr,
4864 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
4865 blk_t ref_blk FSCK_ATTR((unused)),
4866 int ref_offset FSCK_ATTR((unused)),
4867 void *priv_data)
4869 struct process_block_struct_1b *p;
4870 e2fsck_t ctx;
4872 if (HOLE_BLKADDR(*block_nr))
4873 return 0;
4874 p = (struct process_block_struct_1b *) priv_data;
4875 ctx = p->ctx;
4877 if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
4878 return 0;
4880 /* OK, this is a duplicate block */
4881 if (p->ino != EXT2_BAD_INO) {
4882 p->pctx->blk = *block_nr;
4883 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
4885 p->dup_blocks++;
4886 ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
4888 add_dupe(ctx, p->ino, *block_nr, p->inode);
4890 return 0;
4894 * Pass 1c: Scan directories for inodes with duplicate blocks. This
4895 * is used so that we can print pathnames when prompting the user for
4896 * what to do.
4898 struct search_dir_struct {
4899 int count;
4900 ext2_ino_t first_inode;
4901 ext2_ino_t max_inode;
4904 static int search_dirent_proc(ext2_ino_t dir, int entry,
4905 struct ext2_dir_entry *dirent,
4906 int offset FSCK_ATTR((unused)),
4907 int blocksize FSCK_ATTR((unused)),
4908 char *buf FSCK_ATTR((unused)),
4909 void *priv_data)
4911 struct search_dir_struct *sd;
4912 struct dup_inode *p;
4913 dnode_t *n;
4915 sd = (struct search_dir_struct *) priv_data;
4917 if (dirent->inode > sd->max_inode)
4918 /* Should abort this inode, but not everything */
4919 return 0;
4921 if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
4922 !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
4923 return 0;
4925 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
4926 if (!n)
4927 return 0;
4928 p = (struct dup_inode *) dnode_get(n);
4929 p->dir = dir;
4930 sd->count--;
4932 return sd->count ? 0 : DIRENT_ABORT;
4936 static void pass1c(e2fsck_t ctx, char *block_buf)
4938 ext2_filsys fs = ctx->fs;
4939 struct search_dir_struct sd;
4940 struct problem_context pctx;
4942 clear_problem_context(&pctx);
4944 if (!(ctx->options & E2F_OPT_PREEN))
4945 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
4948 * Search through all directories to translate inodes to names
4949 * (by searching for the containing directory for that inode.)
4951 sd.count = dup_inode_count;
4952 sd.first_inode = EXT2_FIRST_INODE(fs->super);
4953 sd.max_inode = fs->super->s_inodes_count;
4954 ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
4955 search_dirent_proc, &sd);
4958 static void pass1d(e2fsck_t ctx, char *block_buf)
4960 ext2_filsys fs = ctx->fs;
4961 struct dup_inode *p, *t;
4962 struct dup_block *q;
4963 ext2_ino_t *shared, ino;
4964 int shared_len;
4965 int i;
4966 int file_ok;
4967 int meta_data = 0;
4968 struct problem_context pctx;
4969 dnode_t *n, *m;
4970 struct block_el *s;
4971 struct inode_el *r;
4973 clear_problem_context(&pctx);
4975 if (!(ctx->options & E2F_OPT_PREEN))
4976 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
4977 e2fsck_read_bitmaps(ctx);
4979 pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
4980 fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
4981 shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
4982 sizeof(ext2_ino_t) * dict_count(&ino_dict),
4983 "Shared inode list");
4984 for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
4985 p = (struct dup_inode *) dnode_get(n);
4986 shared_len = 0;
4987 file_ok = 1;
4988 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
4989 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
4990 continue;
4993 * Find all of the inodes which share blocks with this
4994 * one. First we find all of the duplicate blocks
4995 * belonging to this inode, and then search each block
4996 * get the list of inodes, and merge them together.
4998 for (s = p->block_list; s; s = s->next) {
4999 m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
5000 if (!m)
5001 continue; /* Should never happen... */
5002 q = (struct dup_block *) dnode_get(m);
5003 if (q->num_bad > 1)
5004 file_ok = 0;
5005 if (check_if_fs_block(ctx, s->block)) {
5006 file_ok = 0;
5007 meta_data = 1;
5011 * Add all inodes used by this block to the
5012 * shared[] --- which is a unique list, so
5013 * if an inode is already in shared[], don't
5014 * add it again.
5016 for (r = q->inode_list; r; r = r->next) {
5017 if (r->inode == ino)
5018 continue;
5019 for (i = 0; i < shared_len; i++)
5020 if (shared[i] == r->inode)
5021 break;
5022 if (i == shared_len) {
5023 shared[shared_len++] = r->inode;
5029 * Report the inode that we are working on
5031 pctx.inode = &p->inode;
5032 pctx.ino = ino;
5033 pctx.dir = p->dir;
5034 pctx.blkcount = p->num_dupblocks;
5035 pctx.num = meta_data ? shared_len+1 : shared_len;
5036 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
5037 pctx.blkcount = 0;
5038 pctx.num = 0;
5040 if (meta_data)
5041 fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
5043 for (i = 0; i < shared_len; i++) {
5044 m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
5045 if (!m)
5046 continue; /* should never happen */
5047 t = (struct dup_inode *) dnode_get(m);
5049 * Report the inode that we are sharing with
5051 pctx.inode = &t->inode;
5052 pctx.ino = shared[i];
5053 pctx.dir = t->dir;
5054 fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
5056 if (file_ok) {
5057 fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
5058 continue;
5060 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
5061 pctx.errcode = clone_file(ctx, ino, p, block_buf);
5062 if (pctx.errcode)
5063 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
5064 else
5065 continue;
5067 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
5068 delete_file(ctx, ino, p, block_buf);
5069 else
5070 ext2fs_unmark_valid(fs);
5072 ext2fs_free_mem(&shared);
5076 * Drop the refcount on the dup_block structure, and clear the entry
5077 * in the block_dup_map if appropriate.
5079 static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
5081 p->num_bad--;
5082 if (p->num_bad <= 0 ||
5083 (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
5084 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
5087 static int delete_file_block(ext2_filsys fs,
5088 blk_t *block_nr,
5089 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
5090 blk_t ref_block FSCK_ATTR((unused)),
5091 int ref_offset FSCK_ATTR((unused)),
5092 void *priv_data)
5094 struct process_block_struct_1b *pb;
5095 struct dup_block *p;
5096 dnode_t *n;
5097 e2fsck_t ctx;
5099 pb = (struct process_block_struct_1b *) priv_data;
5100 ctx = pb->ctx;
5102 if (HOLE_BLKADDR(*block_nr))
5103 return 0;
5105 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5106 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5107 if (n) {
5108 p = (struct dup_block *) dnode_get(n);
5109 decrement_badcount(ctx, *block_nr, p);
5110 } else
5111 bb_error_msg(_("internal error; can't find dup_blk for %d"),
5112 *block_nr);
5113 } else {
5114 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
5115 ext2fs_block_alloc_stats(fs, *block_nr, -1);
5118 return 0;
5121 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5122 struct dup_inode *dp, char* block_buf)
5124 ext2_filsys fs = ctx->fs;
5125 struct process_block_struct_1b pb;
5126 struct ext2_inode inode;
5127 struct problem_context pctx;
5128 unsigned int count;
5130 clear_problem_context(&pctx);
5131 pctx.ino = pb.ino = ino;
5132 pb.dup_blocks = dp->num_dupblocks;
5133 pb.ctx = ctx;
5134 pctx.str = "delete_file";
5136 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5137 if (ext2fs_inode_has_valid_blocks(&inode))
5138 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5139 delete_file_block, &pb);
5140 if (pctx.errcode)
5141 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5142 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5143 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5144 if (ctx->inode_bad_map)
5145 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
5146 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
5148 /* Inode may have changed by block_iterate, so reread it */
5149 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5150 inode.i_links_count = 0;
5151 inode.i_dtime = time(NULL);
5152 if (inode.i_file_acl &&
5153 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
5154 count = 1;
5155 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
5156 block_buf, -1, &count);
5157 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
5158 pctx.errcode = 0;
5159 count = 1;
5161 if (pctx.errcode) {
5162 pctx.blk = inode.i_file_acl;
5163 fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
5166 * If the count is zero, then arrange to have the
5167 * block deleted. If the block is in the block_dup_map,
5168 * also call delete_file_block since it will take care
5169 * of keeping the accounting straight.
5171 if ((count == 0) ||
5172 ext2fs_test_block_bitmap(ctx->block_dup_map,
5173 inode.i_file_acl))
5174 delete_file_block(fs, &inode.i_file_acl,
5175 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
5177 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
5180 struct clone_struct {
5181 errcode_t errcode;
5182 ext2_ino_t dir;
5183 char *buf;
5184 e2fsck_t ctx;
5187 static int clone_file_block(ext2_filsys fs,
5188 blk_t *block_nr,
5189 e2_blkcnt_t blockcnt,
5190 blk_t ref_block FSCK_ATTR((unused)),
5191 int ref_offset FSCK_ATTR((unused)),
5192 void *priv_data)
5194 struct dup_block *p;
5195 blk_t new_block;
5196 errcode_t retval;
5197 struct clone_struct *cs = (struct clone_struct *) priv_data;
5198 dnode_t *n;
5199 e2fsck_t ctx;
5201 ctx = cs->ctx;
5203 if (HOLE_BLKADDR(*block_nr))
5204 return 0;
5206 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5207 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5208 if (n) {
5209 p = (struct dup_block *) dnode_get(n);
5210 retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
5211 &new_block);
5212 if (retval) {
5213 cs->errcode = retval;
5214 return BLOCK_ABORT;
5216 if (cs->dir && (blockcnt >= 0)) {
5217 retval = ext2fs_set_dir_block(fs->dblist,
5218 cs->dir, new_block, blockcnt);
5219 if (retval) {
5220 cs->errcode = retval;
5221 return BLOCK_ABORT;
5225 retval = io_channel_read_blk(fs->io, *block_nr, 1,
5226 cs->buf);
5227 if (retval) {
5228 cs->errcode = retval;
5229 return BLOCK_ABORT;
5231 retval = io_channel_write_blk(fs->io, new_block, 1,
5232 cs->buf);
5233 if (retval) {
5234 cs->errcode = retval;
5235 return BLOCK_ABORT;
5237 decrement_badcount(ctx, *block_nr, p);
5238 *block_nr = new_block;
5239 ext2fs_mark_block_bitmap(ctx->block_found_map,
5240 new_block);
5241 ext2fs_mark_block_bitmap(fs->block_map, new_block);
5242 return BLOCK_CHANGED;
5243 } else
5244 bb_error_msg(_("internal error; can't find dup_blk for %d"),
5245 *block_nr);
5247 return 0;
5250 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5251 struct dup_inode *dp, char* block_buf)
5253 ext2_filsys fs = ctx->fs;
5254 errcode_t retval;
5255 struct clone_struct cs;
5256 struct problem_context pctx;
5257 blk_t blk;
5258 dnode_t *n;
5259 struct inode_el *ino_el;
5260 struct dup_block *db;
5261 struct dup_inode *di;
5263 clear_problem_context(&pctx);
5264 cs.errcode = 0;
5265 cs.dir = 0;
5266 cs.ctx = ctx;
5267 retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
5268 if (retval)
5269 return retval;
5271 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
5272 cs.dir = ino;
5274 pctx.ino = ino;
5275 pctx.str = "clone_file";
5276 if (ext2fs_inode_has_valid_blocks(&dp->inode))
5277 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5278 clone_file_block, &cs);
5279 ext2fs_mark_bb_dirty(fs);
5280 if (pctx.errcode) {
5281 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5282 retval = pctx.errcode;
5283 goto errout;
5285 if (cs.errcode) {
5286 bb_error_msg(_("returned from clone_file_block"));
5287 retval = cs.errcode;
5288 goto errout;
5290 /* The inode may have changed on disk, so we have to re-read it */
5291 e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
5292 blk = dp->inode.i_file_acl;
5293 if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
5294 BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
5295 BLOCK_CHANGED)) {
5296 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
5298 * If we cloned the EA block, find all other inodes
5299 * which refered to that EA block, and modify
5300 * them to point to the new EA block.
5302 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5303 db = (struct dup_block *) dnode_get(n);
5304 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
5305 if (ino_el->inode == ino)
5306 continue;
5307 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
5308 di = (struct dup_inode *) dnode_get(n);
5309 if (di->inode.i_file_acl == blk) {
5310 di->inode.i_file_acl = dp->inode.i_file_acl;
5311 e2fsck_write_inode(ctx, ino_el->inode,
5312 &di->inode, "clone file EA");
5313 decrement_badcount(ctx, blk, db);
5317 retval = 0;
5318 errout:
5319 ext2fs_free_mem(&cs.buf);
5320 return retval;
5324 * This routine returns 1 if a block overlaps with one of the superblocks,
5325 * group descriptors, inode bitmaps, or block bitmaps.
5327 static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
5329 ext2_filsys fs = ctx->fs;
5330 blk_t block;
5331 dgrp_t i;
5333 block = fs->super->s_first_data_block;
5334 for (i = 0; i < fs->group_desc_count; i++) {
5336 /* Check superblocks/block group descriptros */
5337 if (ext2fs_bg_has_super(fs, i)) {
5338 if (test_block >= block &&
5339 (test_block <= block + fs->desc_blocks))
5340 return 1;
5343 /* Check the inode table */
5344 if ((fs->group_desc[i].bg_inode_table) &&
5345 (test_block >= fs->group_desc[i].bg_inode_table) &&
5346 (test_block < (fs->group_desc[i].bg_inode_table +
5347 fs->inode_blocks_per_group)))
5348 return 1;
5350 /* Check the bitmap blocks */
5351 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
5352 (test_block == fs->group_desc[i].bg_inode_bitmap))
5353 return 1;
5355 block += fs->super->s_blocks_per_group;
5357 return 0;
5360 * pass2.c --- check directory structure
5362 * Pass 2 of e2fsck iterates through all active directory inodes, and
5363 * applies to following tests to each directory entry in the directory
5364 * blocks in the inodes:
5366 * - The length of the directory entry (rec_len) should be at
5367 * least 8 bytes, and no more than the remaining space
5368 * left in the directory block.
5369 * - The length of the name in the directory entry (name_len)
5370 * should be less than (rec_len - 8).
5371 * - The inode number in the directory entry should be within
5372 * legal bounds.
5373 * - The inode number should refer to a in-use inode.
5374 * - The first entry should be '.', and its inode should be
5375 * the inode of the directory.
5376 * - The second entry should be '..'.
5378 * To minimize disk seek time, the directory blocks are processed in
5379 * sorted order of block numbers.
5381 * Pass 2 also collects the following information:
5382 * - The inode numbers of the subdirectories for each directory.
5384 * Pass 2 relies on the following information from previous passes:
5385 * - The directory information collected in pass 1.
5386 * - The inode_used_map bitmap
5387 * - The inode_bad_map bitmap
5388 * - The inode_dir_map bitmap
5390 * Pass 2 frees the following data structures
5391 * - The inode_bad_map bitmap
5392 * - The inode_reg_map bitmap
5396 * Keeps track of how many times an inode is referenced.
5398 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
5399 static int check_dir_block(ext2_filsys fs,
5400 struct ext2_db_entry *dir_blocks_info,
5401 void *priv_data);
5402 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
5403 struct problem_context *pctx);
5404 static int update_dir_block(ext2_filsys fs,
5405 blk_t *block_nr,
5406 e2_blkcnt_t blockcnt,
5407 blk_t ref_block,
5408 int ref_offset,
5409 void *priv_data);
5410 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
5411 static int htree_depth(struct dx_dir_info *dx_dir,
5412 struct dx_dirblock_info *dx_db);
5413 static int special_dir_block_cmp(const void *a, const void *b);
5415 struct check_dir_struct {
5416 char *buf;
5417 struct problem_context pctx;
5418 int count, max;
5419 e2fsck_t ctx;
5422 static void e2fsck_pass2(e2fsck_t ctx)
5424 struct ext2_super_block *sb = ctx->fs->super;
5425 struct problem_context pctx;
5426 ext2_filsys fs = ctx->fs;
5427 char *buf;
5428 struct dir_info *dir;
5429 struct check_dir_struct cd;
5430 struct dx_dir_info *dx_dir;
5431 struct dx_dirblock_info *dx_db, *dx_parent;
5432 int b;
5433 int i, depth;
5434 problem_t code;
5435 int bad_dir;
5437 clear_problem_context(&cd.pctx);
5439 /* Pass 2 */
5441 if (!(ctx->options & E2F_OPT_PREEN))
5442 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
5444 cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
5445 0, ctx->inode_link_info,
5446 &ctx->inode_count);
5447 if (cd.pctx.errcode) {
5448 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
5449 ctx->flags |= E2F_FLAG_ABORT;
5450 return;
5452 buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
5453 "directory scan buffer");
5456 * Set up the parent pointer for the root directory, if
5457 * present. (If the root directory is not present, we will
5458 * create it in pass 3.)
5460 dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
5461 if (dir)
5462 dir->parent = EXT2_ROOT_INO;
5464 cd.buf = buf;
5465 cd.ctx = ctx;
5466 cd.count = 1;
5467 cd.max = ext2fs_dblist_count(fs->dblist);
5469 if (ctx->progress)
5470 (void) (ctx->progress)(ctx, 2, 0, cd.max);
5472 if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
5473 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
5475 cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
5476 &cd);
5477 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5478 return;
5479 if (cd.pctx.errcode) {
5480 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
5481 ctx->flags |= E2F_FLAG_ABORT;
5482 return;
5485 #ifdef ENABLE_HTREE
5486 for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
5487 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5488 return;
5489 if (dx_dir->numblocks == 0)
5490 continue;
5491 clear_problem_context(&pctx);
5492 bad_dir = 0;
5493 pctx.dir = dx_dir->ino;
5494 dx_db = dx_dir->dx_block;
5495 if (dx_db->flags & DX_FLAG_REFERENCED)
5496 dx_db->flags |= DX_FLAG_DUP_REF;
5497 else
5498 dx_db->flags |= DX_FLAG_REFERENCED;
5500 * Find all of the first and last leaf blocks, and
5501 * update their parent's min and max hash values
5503 for (b=0, dx_db = dx_dir->dx_block;
5504 b < dx_dir->numblocks;
5505 b++, dx_db++) {
5506 if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
5507 !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
5508 continue;
5509 dx_parent = &dx_dir->dx_block[dx_db->parent];
5511 * XXX Make sure dx_parent->min_hash > dx_db->min_hash
5513 if (dx_db->flags & DX_FLAG_FIRST)
5514 dx_parent->min_hash = dx_db->min_hash;
5516 * XXX Make sure dx_parent->max_hash < dx_db->max_hash
5518 if (dx_db->flags & DX_FLAG_LAST)
5519 dx_parent->max_hash = dx_db->max_hash;
5522 for (b=0, dx_db = dx_dir->dx_block;
5523 b < dx_dir->numblocks;
5524 b++, dx_db++) {
5525 pctx.blkcount = b;
5526 pctx.group = dx_db->parent;
5527 code = 0;
5528 if (!(dx_db->flags & DX_FLAG_FIRST) &&
5529 (dx_db->min_hash < dx_db->node_min_hash)) {
5530 pctx.blk = dx_db->min_hash;
5531 pctx.blk2 = dx_db->node_min_hash;
5532 code = PR_2_HTREE_MIN_HASH;
5533 fix_problem(ctx, code, &pctx);
5534 bad_dir++;
5536 if (dx_db->type == DX_DIRBLOCK_LEAF) {
5537 depth = htree_depth(dx_dir, dx_db);
5538 if (depth != dx_dir->depth) {
5539 code = PR_2_HTREE_BAD_DEPTH;
5540 fix_problem(ctx, code, &pctx);
5541 bad_dir++;
5545 * This test doesn't apply for the root block
5546 * at block #0
5548 if (b &&
5549 (dx_db->max_hash > dx_db->node_max_hash)) {
5550 pctx.blk = dx_db->max_hash;
5551 pctx.blk2 = dx_db->node_max_hash;
5552 code = PR_2_HTREE_MAX_HASH;
5553 fix_problem(ctx, code, &pctx);
5554 bad_dir++;
5556 if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
5557 code = PR_2_HTREE_NOTREF;
5558 fix_problem(ctx, code, &pctx);
5559 bad_dir++;
5560 } else if (dx_db->flags & DX_FLAG_DUP_REF) {
5561 code = PR_2_HTREE_DUPREF;
5562 fix_problem(ctx, code, &pctx);
5563 bad_dir++;
5565 if (code == 0)
5566 continue;
5568 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
5569 clear_htree(ctx, dx_dir->ino);
5570 dx_dir->numblocks = 0;
5573 #endif
5574 ext2fs_free_mem(&buf);
5575 ext2fs_free_dblist(fs->dblist);
5577 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
5578 ctx->inode_bad_map = 0;
5579 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
5580 ctx->inode_reg_map = 0;
5582 clear_problem_context(&pctx);
5583 if (ctx->large_files) {
5584 if (!(sb->s_feature_ro_compat &
5585 EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
5586 fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
5587 sb->s_feature_ro_compat |=
5588 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5589 ext2fs_mark_super_dirty(fs);
5591 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
5592 fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
5593 ext2fs_update_dynamic_rev(fs);
5594 ext2fs_mark_super_dirty(fs);
5596 } else if (!ctx->large_files &&
5597 (sb->s_feature_ro_compat &
5598 EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
5599 if (fs->flags & EXT2_FLAG_RW) {
5600 sb->s_feature_ro_compat &=
5601 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5602 ext2fs_mark_super_dirty(fs);
5607 #define MAX_DEPTH 32000
5608 static int htree_depth(struct dx_dir_info *dx_dir,
5609 struct dx_dirblock_info *dx_db)
5611 int depth = 0;
5613 while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
5614 dx_db = &dx_dir->dx_block[dx_db->parent];
5615 depth++;
5617 return depth;
5620 static int dict_de_cmp(const void *a, const void *b)
5622 const struct ext2_dir_entry *de_a, *de_b;
5623 int a_len, b_len;
5625 de_a = (const struct ext2_dir_entry *) a;
5626 a_len = de_a->name_len & 0xFF;
5627 de_b = (const struct ext2_dir_entry *) b;
5628 b_len = de_b->name_len & 0xFF;
5630 if (a_len != b_len)
5631 return (a_len - b_len);
5633 return strncmp(de_a->name, de_b->name, a_len);
5637 * This is special sort function that makes sure that directory blocks
5638 * with a dirblock of zero are sorted to the beginning of the list.
5639 * This guarantees that the root node of the htree directories are
5640 * processed first, so we know what hash version to use.
5642 static int special_dir_block_cmp(const void *a, const void *b)
5644 const struct ext2_db_entry *db_a =
5645 (const struct ext2_db_entry *) a;
5646 const struct ext2_db_entry *db_b =
5647 (const struct ext2_db_entry *) b;
5649 if (db_a->blockcnt && !db_b->blockcnt)
5650 return 1;
5652 if (!db_a->blockcnt && db_b->blockcnt)
5653 return -1;
5655 if (db_a->blk != db_b->blk)
5656 return (int) (db_a->blk - db_b->blk);
5658 if (db_a->ino != db_b->ino)
5659 return (int) (db_a->ino - db_b->ino);
5661 return (int) (db_a->blockcnt - db_b->blockcnt);
5666 * Make sure the first entry in the directory is '.', and that the
5667 * directory entry is sane.
5669 static int check_dot(e2fsck_t ctx,
5670 struct ext2_dir_entry *dirent,
5671 ext2_ino_t ino, struct problem_context *pctx)
5673 struct ext2_dir_entry *nextdir;
5674 int status = 0;
5675 int created = 0;
5676 int new_len;
5677 int problem = 0;
5679 if (!dirent->inode)
5680 problem = PR_2_MISSING_DOT;
5681 else if (((dirent->name_len & 0xFF) != 1) ||
5682 (dirent->name[0] != '.'))
5683 problem = PR_2_1ST_NOT_DOT;
5684 else if (dirent->name[1] != '\0')
5685 problem = PR_2_DOT_NULL_TERM;
5687 if (problem) {
5688 if (fix_problem(ctx, problem, pctx)) {
5689 if (dirent->rec_len < 12)
5690 dirent->rec_len = 12;
5691 dirent->inode = ino;
5692 dirent->name_len = 1;
5693 dirent->name[0] = '.';
5694 dirent->name[1] = '\0';
5695 status = 1;
5696 created = 1;
5699 if (dirent->inode != ino) {
5700 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
5701 dirent->inode = ino;
5702 status = 1;
5705 if (dirent->rec_len > 12) {
5706 new_len = dirent->rec_len - 12;
5707 if (new_len > 12) {
5708 if (created ||
5709 fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
5710 nextdir = (struct ext2_dir_entry *)
5711 ((char *) dirent + 12);
5712 dirent->rec_len = 12;
5713 nextdir->rec_len = new_len;
5714 nextdir->inode = 0;
5715 nextdir->name_len = 0;
5716 status = 1;
5720 return status;
5724 * Make sure the second entry in the directory is '..', and that the
5725 * directory entry is sane. We do not check the inode number of '..'
5726 * here; this gets done in pass 3.
5728 static int check_dotdot(e2fsck_t ctx,
5729 struct ext2_dir_entry *dirent,
5730 struct dir_info *dir, struct problem_context *pctx)
5732 int problem = 0;
5734 if (!dirent->inode)
5735 problem = PR_2_MISSING_DOT_DOT;
5736 else if (((dirent->name_len & 0xFF) != 2) ||
5737 (dirent->name[0] != '.') ||
5738 (dirent->name[1] != '.'))
5739 problem = PR_2_2ND_NOT_DOT_DOT;
5740 else if (dirent->name[2] != '\0')
5741 problem = PR_2_DOT_DOT_NULL_TERM;
5743 if (problem) {
5744 if (fix_problem(ctx, problem, pctx)) {
5745 if (dirent->rec_len < 12)
5746 dirent->rec_len = 12;
5748 * Note: we don't have the parent inode just
5749 * yet, so we will fill it in with the root
5750 * inode. This will get fixed in pass 3.
5752 dirent->inode = EXT2_ROOT_INO;
5753 dirent->name_len = 2;
5754 dirent->name[0] = '.';
5755 dirent->name[1] = '.';
5756 dirent->name[2] = '\0';
5757 return 1;
5759 return 0;
5761 dir->dotdot = dirent->inode;
5762 return 0;
5766 * Check to make sure a directory entry doesn't contain any illegal
5767 * characters.
5769 static int check_name(e2fsck_t ctx,
5770 struct ext2_dir_entry *dirent,
5771 struct problem_context *pctx)
5773 int i;
5774 int fixup = -1;
5775 int ret = 0;
5777 for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
5778 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
5779 if (fixup < 0) {
5780 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
5782 if (fixup) {
5783 dirent->name[i] = '.';
5784 ret = 1;
5788 return ret;
5792 * Check the directory filetype (if present)
5796 * Given a mode, return the ext2 file type
5798 static int ext2_file_type(unsigned int mode)
5800 if (LINUX_S_ISREG(mode))
5801 return EXT2_FT_REG_FILE;
5803 if (LINUX_S_ISDIR(mode))
5804 return EXT2_FT_DIR;
5806 if (LINUX_S_ISCHR(mode))
5807 return EXT2_FT_CHRDEV;
5809 if (LINUX_S_ISBLK(mode))
5810 return EXT2_FT_BLKDEV;
5812 if (LINUX_S_ISLNK(mode))
5813 return EXT2_FT_SYMLINK;
5815 if (LINUX_S_ISFIFO(mode))
5816 return EXT2_FT_FIFO;
5818 if (LINUX_S_ISSOCK(mode))
5819 return EXT2_FT_SOCK;
5821 return 0;
5824 static int check_filetype(e2fsck_t ctx,
5825 struct ext2_dir_entry *dirent,
5826 struct problem_context *pctx)
5828 int filetype = dirent->name_len >> 8;
5829 int should_be = EXT2_FT_UNKNOWN;
5830 struct ext2_inode inode;
5832 if (!(ctx->fs->super->s_feature_incompat &
5833 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
5834 if (filetype == 0 ||
5835 !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
5836 return 0;
5837 dirent->name_len = dirent->name_len & 0xFF;
5838 return 1;
5841 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
5842 should_be = EXT2_FT_DIR;
5843 } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
5844 dirent->inode)) {
5845 should_be = EXT2_FT_REG_FILE;
5846 } else if (ctx->inode_bad_map &&
5847 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
5848 dirent->inode))
5849 should_be = 0;
5850 else {
5851 e2fsck_read_inode(ctx, dirent->inode, &inode,
5852 "check_filetype");
5853 should_be = ext2_file_type(inode.i_mode);
5855 if (filetype == should_be)
5856 return 0;
5857 pctx->num = should_be;
5859 if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
5860 pctx) == 0)
5861 return 0;
5863 dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
5864 return 1;
5867 #ifdef ENABLE_HTREE
5868 static void parse_int_node(ext2_filsys fs,
5869 struct ext2_db_entry *db,
5870 struct check_dir_struct *cd,
5871 struct dx_dir_info *dx_dir,
5872 char *block_buf)
5874 struct ext2_dx_root_info *root;
5875 struct ext2_dx_entry *ent;
5876 struct ext2_dx_countlimit *limit;
5877 struct dx_dirblock_info *dx_db;
5878 int i, expect_limit, count;
5879 blk_t blk;
5880 ext2_dirhash_t min_hash = 0xffffffff;
5881 ext2_dirhash_t max_hash = 0;
5882 ext2_dirhash_t hash = 0, prev_hash;
5884 if (db->blockcnt == 0) {
5885 root = (struct ext2_dx_root_info *) (block_buf + 24);
5886 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5887 } else {
5888 ent = (struct ext2_dx_entry *) (block_buf+8);
5890 limit = (struct ext2_dx_countlimit *) ent;
5892 count = ext2fs_le16_to_cpu(limit->count);
5893 expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
5894 sizeof(struct ext2_dx_entry);
5895 if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5896 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
5897 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
5898 goto clear_and_exit;
5900 if (count > expect_limit) {
5901 cd->pctx.num = count;
5902 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
5903 goto clear_and_exit;
5904 count = expect_limit;
5907 for (i=0; i < count; i++) {
5908 prev_hash = hash;
5909 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5910 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5911 /* Check to make sure the block is valid */
5912 if (blk > (blk_t) dx_dir->numblocks) {
5913 cd->pctx.blk = blk;
5914 if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
5915 &cd->pctx))
5916 goto clear_and_exit;
5918 if (hash < prev_hash &&
5919 fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
5920 goto clear_and_exit;
5921 dx_db = &dx_dir->dx_block[blk];
5922 if (dx_db->flags & DX_FLAG_REFERENCED) {
5923 dx_db->flags |= DX_FLAG_DUP_REF;
5924 } else {
5925 dx_db->flags |= DX_FLAG_REFERENCED;
5926 dx_db->parent = db->blockcnt;
5928 if (hash < min_hash)
5929 min_hash = hash;
5930 if (hash > max_hash)
5931 max_hash = hash;
5932 dx_db->node_min_hash = hash;
5933 if ((i+1) < count)
5934 dx_db->node_max_hash =
5935 ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
5936 else {
5937 dx_db->node_max_hash = 0xfffffffe;
5938 dx_db->flags |= DX_FLAG_LAST;
5940 if (i == 0)
5941 dx_db->flags |= DX_FLAG_FIRST;
5943 dx_db = &dx_dir->dx_block[db->blockcnt];
5944 dx_db->min_hash = min_hash;
5945 dx_db->max_hash = max_hash;
5946 return;
5948 clear_and_exit:
5949 clear_htree(cd->ctx, cd->pctx.ino);
5950 dx_dir->numblocks = 0;
5952 #endif /* ENABLE_HTREE */
5955 * Given a busted directory, try to salvage it somehow.
5958 static void salvage_directory(ext2_filsys fs,
5959 struct ext2_dir_entry *dirent,
5960 struct ext2_dir_entry *prev,
5961 unsigned int *offset)
5963 char *cp = (char *) dirent;
5964 int left = fs->blocksize - *offset - dirent->rec_len;
5965 int name_len = dirent->name_len & 0xFF;
5968 * Special case of directory entry of size 8: copy what's left
5969 * of the directory block up to cover up the invalid hole.
5971 if ((left >= 12) && (dirent->rec_len == 8)) {
5972 memmove(cp, cp+8, left);
5973 memset(cp + left, 0, 8);
5974 return;
5977 * If the directory entry overruns the end of the directory
5978 * block, and the name is small enough to fit, then adjust the
5979 * record length.
5981 if ((left < 0) &&
5982 (name_len + 8 <= dirent->rec_len + left) &&
5983 dirent->inode <= fs->super->s_inodes_count &&
5984 strnlen(dirent->name, name_len) == name_len) {
5985 dirent->rec_len += left;
5986 return;
5989 * If the directory entry is a multiple of four, so it is
5990 * valid, let the previous directory entry absorb the invalid
5991 * one.
5993 if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
5994 prev->rec_len += dirent->rec_len;
5995 *offset += dirent->rec_len;
5996 return;
5999 * Default salvage method --- kill all of the directory
6000 * entries for the rest of the block. We will either try to
6001 * absorb it into the previous directory entry, or create a
6002 * new empty directory entry the rest of the directory block.
6004 if (prev) {
6005 prev->rec_len += fs->blocksize - *offset;
6006 *offset = fs->blocksize;
6007 } else {
6008 dirent->rec_len = fs->blocksize - *offset;
6009 dirent->name_len = 0;
6010 dirent->inode = 0;
6014 static int check_dir_block(ext2_filsys fs,
6015 struct ext2_db_entry *db,
6016 void *priv_data)
6018 struct dir_info *subdir, *dir;
6019 struct dx_dir_info *dx_dir;
6020 #ifdef ENABLE_HTREE
6021 struct dx_dirblock_info *dx_db = NULL;
6022 #endif /* ENABLE_HTREE */
6023 struct ext2_dir_entry *dirent, *prev;
6024 ext2_dirhash_t hash;
6025 unsigned int offset = 0;
6026 int dir_modified = 0;
6027 int dot_state;
6028 blk_t block_nr = db->blk;
6029 ext2_ino_t ino = db->ino;
6030 __u16 links;
6031 struct check_dir_struct *cd;
6032 char *buf;
6033 e2fsck_t ctx;
6034 int problem;
6035 struct ext2_dx_root_info *root;
6036 struct ext2_dx_countlimit *limit;
6037 static dict_t de_dict;
6038 struct problem_context pctx;
6039 int dups_found = 0;
6041 cd = (struct check_dir_struct *) priv_data;
6042 buf = cd->buf;
6043 ctx = cd->ctx;
6045 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6046 return DIRENT_ABORT;
6048 if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
6049 return DIRENT_ABORT;
6052 * Make sure the inode is still in use (could have been
6053 * deleted in the duplicate/bad blocks pass.
6055 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
6056 return 0;
6058 cd->pctx.ino = ino;
6059 cd->pctx.blk = block_nr;
6060 cd->pctx.blkcount = db->blockcnt;
6061 cd->pctx.ino2 = 0;
6062 cd->pctx.dirent = 0;
6063 cd->pctx.num = 0;
6065 if (db->blk == 0) {
6066 if (allocate_dir_block(ctx, db, &cd->pctx))
6067 return 0;
6068 block_nr = db->blk;
6071 if (db->blockcnt)
6072 dot_state = 2;
6073 else
6074 dot_state = 0;
6076 if (ctx->dirs_to_hash &&
6077 ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
6078 dups_found++;
6080 cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
6081 if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
6082 cd->pctx.errcode = 0; /* We'll handle this ourselves */
6083 if (cd->pctx.errcode) {
6084 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
6085 ctx->flags |= E2F_FLAG_ABORT;
6086 return DIRENT_ABORT;
6088 memset(buf, 0, fs->blocksize);
6090 #ifdef ENABLE_HTREE
6091 dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
6092 if (dx_dir && dx_dir->numblocks) {
6093 if (db->blockcnt >= dx_dir->numblocks) {
6094 printf("XXX should never happen!!!\n");
6095 abort();
6097 dx_db = &dx_dir->dx_block[db->blockcnt];
6098 dx_db->type = DX_DIRBLOCK_LEAF;
6099 dx_db->phys = block_nr;
6100 dx_db->min_hash = ~0;
6101 dx_db->max_hash = 0;
6103 dirent = (struct ext2_dir_entry *) buf;
6104 limit = (struct ext2_dx_countlimit *) (buf+8);
6105 if (db->blockcnt == 0) {
6106 root = (struct ext2_dx_root_info *) (buf + 24);
6107 dx_db->type = DX_DIRBLOCK_ROOT;
6108 dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
6109 if ((root->reserved_zero ||
6110 root->info_length < 8 ||
6111 root->indirect_levels > 1) &&
6112 fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
6113 clear_htree(ctx, ino);
6114 dx_dir->numblocks = 0;
6115 dx_db = 0;
6117 dx_dir->hashversion = root->hash_version;
6118 dx_dir->depth = root->indirect_levels + 1;
6119 } else if ((dirent->inode == 0) &&
6120 (dirent->rec_len == fs->blocksize) &&
6121 (dirent->name_len == 0) &&
6122 (ext2fs_le16_to_cpu(limit->limit) ==
6123 ((fs->blocksize-8) /
6124 sizeof(struct ext2_dx_entry))))
6125 dx_db->type = DX_DIRBLOCK_NODE;
6127 #endif /* ENABLE_HTREE */
6129 dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
6130 prev = 0;
6131 do {
6132 problem = 0;
6133 dirent = (struct ext2_dir_entry *) (buf + offset);
6134 cd->pctx.dirent = dirent;
6135 cd->pctx.num = offset;
6136 if (((offset + dirent->rec_len) > fs->blocksize) ||
6137 (dirent->rec_len < 12) ||
6138 ((dirent->rec_len % 4) != 0) ||
6139 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
6140 if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
6141 salvage_directory(fs, dirent, prev, &offset);
6142 dir_modified++;
6143 continue;
6144 } else
6145 goto abort_free_dict;
6147 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
6148 if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
6149 dirent->name_len = EXT2_NAME_LEN;
6150 dir_modified++;
6154 if (dot_state == 0) {
6155 if (check_dot(ctx, dirent, ino, &cd->pctx))
6156 dir_modified++;
6157 } else if (dot_state == 1) {
6158 dir = e2fsck_get_dir_info(ctx, ino);
6159 if (!dir) {
6160 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6161 goto abort_free_dict;
6163 if (check_dotdot(ctx, dirent, dir, &cd->pctx))
6164 dir_modified++;
6165 } else if (dirent->inode == ino) {
6166 problem = PR_2_LINK_DOT;
6167 if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
6168 dirent->inode = 0;
6169 dir_modified++;
6170 goto next;
6173 if (!dirent->inode)
6174 goto next;
6177 * Make sure the inode listed is a legal one.
6179 if (((dirent->inode != EXT2_ROOT_INO) &&
6180 (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
6181 (dirent->inode > fs->super->s_inodes_count)) {
6182 problem = PR_2_BAD_INO;
6183 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
6184 dirent->inode))) {
6186 * If the inode is unused, offer to clear it.
6188 problem = PR_2_UNUSED_INODE;
6189 } else if ((dot_state > 1) &&
6190 ((dirent->name_len & 0xFF) == 1) &&
6191 (dirent->name[0] == '.')) {
6193 * If there's a '.' entry in anything other
6194 * than the first directory entry, it's a
6195 * duplicate entry that should be removed.
6197 problem = PR_2_DUP_DOT;
6198 } else if ((dot_state > 1) &&
6199 ((dirent->name_len & 0xFF) == 2) &&
6200 (dirent->name[0] == '.') &&
6201 (dirent->name[1] == '.')) {
6203 * If there's a '..' entry in anything other
6204 * than the second directory entry, it's a
6205 * duplicate entry that should be removed.
6207 problem = PR_2_DUP_DOT_DOT;
6208 } else if ((dot_state > 1) &&
6209 (dirent->inode == EXT2_ROOT_INO)) {
6211 * Don't allow links to the root directory.
6212 * We check this specially to make sure we
6213 * catch this error case even if the root
6214 * directory hasn't been created yet.
6216 problem = PR_2_LINK_ROOT;
6217 } else if ((dot_state > 1) &&
6218 (dirent->name_len & 0xFF) == 0) {
6220 * Don't allow zero-length directory names.
6222 problem = PR_2_NULL_NAME;
6225 if (problem) {
6226 if (fix_problem(ctx, problem, &cd->pctx)) {
6227 dirent->inode = 0;
6228 dir_modified++;
6229 goto next;
6230 } else {
6231 ext2fs_unmark_valid(fs);
6232 if (problem == PR_2_BAD_INO)
6233 goto next;
6238 * If the inode was marked as having bad fields in
6239 * pass1, process it and offer to fix/clear it.
6240 * (We wait until now so that we can display the
6241 * pathname to the user.)
6243 if (ctx->inode_bad_map &&
6244 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
6245 dirent->inode)) {
6246 if (e2fsck_process_bad_inode(ctx, ino,
6247 dirent->inode,
6248 buf + fs->blocksize)) {
6249 dirent->inode = 0;
6250 dir_modified++;
6251 goto next;
6253 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6254 return DIRENT_ABORT;
6257 if (check_name(ctx, dirent, &cd->pctx))
6258 dir_modified++;
6260 if (check_filetype(ctx, dirent, &cd->pctx))
6261 dir_modified++;
6263 #ifdef ENABLE_HTREE
6264 if (dx_db) {
6265 ext2fs_dirhash(dx_dir->hashversion, dirent->name,
6266 (dirent->name_len & 0xFF),
6267 fs->super->s_hash_seed, &hash, 0);
6268 if (hash < dx_db->min_hash)
6269 dx_db->min_hash = hash;
6270 if (hash > dx_db->max_hash)
6271 dx_db->max_hash = hash;
6273 #endif
6276 * If this is a directory, then mark its parent in its
6277 * dir_info structure. If the parent field is already
6278 * filled in, then this directory has more than one
6279 * hard link. We assume the first link is correct,
6280 * and ask the user if he/she wants to clear this one.
6282 if ((dot_state > 1) &&
6283 (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6284 dirent->inode))) {
6285 subdir = e2fsck_get_dir_info(ctx, dirent->inode);
6286 if (!subdir) {
6287 cd->pctx.ino = dirent->inode;
6288 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6289 goto abort_free_dict;
6291 if (subdir->parent) {
6292 cd->pctx.ino2 = subdir->parent;
6293 if (fix_problem(ctx, PR_2_LINK_DIR,
6294 &cd->pctx)) {
6295 dirent->inode = 0;
6296 dir_modified++;
6297 goto next;
6299 cd->pctx.ino2 = 0;
6300 } else
6301 subdir->parent = ino;
6304 if (dups_found) {
6306 } else if (dict_lookup(&de_dict, dirent)) {
6307 clear_problem_context(&pctx);
6308 pctx.ino = ino;
6309 pctx.dirent = dirent;
6310 fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
6311 if (!ctx->dirs_to_hash)
6312 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
6313 if (ctx->dirs_to_hash)
6314 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6315 dups_found++;
6316 } else
6317 dict_alloc_insert(&de_dict, dirent, dirent);
6319 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
6320 &links);
6321 if (links > 1)
6322 ctx->fs_links_count++;
6323 ctx->fs_total_count++;
6324 next:
6325 prev = dirent;
6326 offset += dirent->rec_len;
6327 dot_state++;
6328 } while (offset < fs->blocksize);
6329 #ifdef ENABLE_HTREE
6330 if (dx_db) {
6331 cd->pctx.dir = cd->pctx.ino;
6332 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
6333 (dx_db->type == DX_DIRBLOCK_NODE))
6334 parse_int_node(fs, db, cd, dx_dir, buf);
6336 #endif /* ENABLE_HTREE */
6337 if (offset != fs->blocksize) {
6338 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
6339 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
6340 dirent->rec_len = cd->pctx.num;
6341 dir_modified++;
6344 if (dir_modified) {
6345 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
6346 if (cd->pctx.errcode) {
6347 if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
6348 &cd->pctx))
6349 goto abort_free_dict;
6351 ext2fs_mark_changed(fs);
6353 dict_free_nodes(&de_dict);
6354 return 0;
6355 abort_free_dict:
6356 dict_free_nodes(&de_dict);
6357 ctx->flags |= E2F_FLAG_ABORT;
6358 return DIRENT_ABORT;
6362 * This function is called to deallocate a block, and is an interator
6363 * functioned called by deallocate inode via ext2fs_iterate_block().
6365 static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
6366 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6367 blk_t ref_block FSCK_ATTR((unused)),
6368 int ref_offset FSCK_ATTR((unused)),
6369 void *priv_data)
6371 e2fsck_t ctx = (e2fsck_t) priv_data;
6373 if (HOLE_BLKADDR(*block_nr))
6374 return 0;
6375 if ((*block_nr < fs->super->s_first_data_block) ||
6376 (*block_nr >= fs->super->s_blocks_count))
6377 return 0;
6378 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6379 ext2fs_block_alloc_stats(fs, *block_nr, -1);
6380 return 0;
6384 * This fuction deallocates an inode
6386 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
6388 ext2_filsys fs = ctx->fs;
6389 struct ext2_inode inode;
6390 struct problem_context pctx;
6391 __u32 count;
6393 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
6394 e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
6395 inode.i_links_count = 0;
6396 inode.i_dtime = time(NULL);
6397 e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
6398 clear_problem_context(&pctx);
6399 pctx.ino = ino;
6402 * Fix up the bitmaps...
6404 e2fsck_read_bitmaps(ctx);
6405 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6406 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6407 if (ctx->inode_bad_map)
6408 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6409 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6411 if (inode.i_file_acl &&
6412 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6413 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6414 block_buf, -1, &count);
6415 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6416 pctx.errcode = 0;
6417 count = 1;
6419 if (pctx.errcode) {
6420 pctx.blk = inode.i_file_acl;
6421 fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
6422 ctx->flags |= E2F_FLAG_ABORT;
6423 return;
6425 if (count == 0) {
6426 ext2fs_unmark_block_bitmap(ctx->block_found_map,
6427 inode.i_file_acl);
6428 ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
6430 inode.i_file_acl = 0;
6433 if (!ext2fs_inode_has_valid_blocks(&inode))
6434 return;
6436 if (LINUX_S_ISREG(inode.i_mode) &&
6437 (inode.i_size_high || inode.i_size & 0x80000000UL))
6438 ctx->large_files--;
6440 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6441 deallocate_inode_block, ctx);
6442 if (pctx.errcode) {
6443 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
6444 ctx->flags |= E2F_FLAG_ABORT;
6445 return;
6450 * This fuction clears the htree flag on an inode
6452 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
6454 struct ext2_inode inode;
6456 e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
6457 inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
6458 e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
6459 if (ctx->dirs_to_hash)
6460 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6464 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
6465 ext2_ino_t ino, char *buf)
6467 ext2_filsys fs = ctx->fs;
6468 struct ext2_inode inode;
6469 int inode_modified = 0;
6470 int not_fixed = 0;
6471 unsigned char *frag, *fsize;
6472 struct problem_context pctx;
6473 int problem = 0;
6475 e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
6477 clear_problem_context(&pctx);
6478 pctx.ino = ino;
6479 pctx.dir = dir;
6480 pctx.inode = &inode;
6482 if (inode.i_file_acl &&
6483 !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
6484 fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
6485 inode.i_file_acl = 0;
6486 #if BB_BIG_ENDIAN
6488 * This is a special kludge to deal with long symlinks
6489 * on big endian systems. i_blocks had already been
6490 * decremented earlier in pass 1, but since i_file_acl
6491 * hadn't yet been cleared, ext2fs_read_inode()
6492 * assumed that the file was short symlink and would
6493 * not have byte swapped i_block[0]. Hence, we have
6494 * to byte-swap it here.
6496 if (LINUX_S_ISLNK(inode.i_mode) &&
6497 (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
6498 (inode.i_blocks == fs->blocksize >> 9))
6499 inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
6500 #endif
6501 inode_modified++;
6502 } else
6503 not_fixed++;
6505 if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
6506 !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
6507 !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
6508 !(LINUX_S_ISSOCK(inode.i_mode)))
6509 problem = PR_2_BAD_MODE;
6510 else if (LINUX_S_ISCHR(inode.i_mode)
6511 && !e2fsck_pass1_check_device_inode(fs, &inode))
6512 problem = PR_2_BAD_CHAR_DEV;
6513 else if (LINUX_S_ISBLK(inode.i_mode)
6514 && !e2fsck_pass1_check_device_inode(fs, &inode))
6515 problem = PR_2_BAD_BLOCK_DEV;
6516 else if (LINUX_S_ISFIFO(inode.i_mode)
6517 && !e2fsck_pass1_check_device_inode(fs, &inode))
6518 problem = PR_2_BAD_FIFO;
6519 else if (LINUX_S_ISSOCK(inode.i_mode)
6520 && !e2fsck_pass1_check_device_inode(fs, &inode))
6521 problem = PR_2_BAD_SOCKET;
6522 else if (LINUX_S_ISLNK(inode.i_mode)
6523 && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
6524 problem = PR_2_INVALID_SYMLINK;
6527 if (problem) {
6528 if (fix_problem(ctx, problem, &pctx)) {
6529 deallocate_inode(ctx, ino, 0);
6530 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6531 return 0;
6532 return 1;
6533 } else
6534 not_fixed++;
6535 problem = 0;
6538 if (inode.i_faddr) {
6539 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
6540 inode.i_faddr = 0;
6541 inode_modified++;
6542 } else
6543 not_fixed++;
6546 switch (fs->super->s_creator_os) {
6547 case EXT2_OS_LINUX:
6548 frag = &inode.osd2.linux2.l_i_frag;
6549 fsize = &inode.osd2.linux2.l_i_fsize;
6550 break;
6551 case EXT2_OS_HURD:
6552 frag = &inode.osd2.hurd2.h_i_frag;
6553 fsize = &inode.osd2.hurd2.h_i_fsize;
6554 break;
6555 case EXT2_OS_MASIX:
6556 frag = &inode.osd2.masix2.m_i_frag;
6557 fsize = &inode.osd2.masix2.m_i_fsize;
6558 break;
6559 default:
6560 frag = fsize = 0;
6562 if (frag && *frag) {
6563 pctx.num = *frag;
6564 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
6565 *frag = 0;
6566 inode_modified++;
6567 } else
6568 not_fixed++;
6569 pctx.num = 0;
6571 if (fsize && *fsize) {
6572 pctx.num = *fsize;
6573 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
6574 *fsize = 0;
6575 inode_modified++;
6576 } else
6577 not_fixed++;
6578 pctx.num = 0;
6581 if (inode.i_file_acl &&
6582 ((inode.i_file_acl < fs->super->s_first_data_block) ||
6583 (inode.i_file_acl >= fs->super->s_blocks_count))) {
6584 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
6585 inode.i_file_acl = 0;
6586 inode_modified++;
6587 } else
6588 not_fixed++;
6590 if (inode.i_dir_acl &&
6591 LINUX_S_ISDIR(inode.i_mode)) {
6592 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
6593 inode.i_dir_acl = 0;
6594 inode_modified++;
6595 } else
6596 not_fixed++;
6599 if (inode_modified)
6600 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
6601 if (!not_fixed)
6602 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6603 return 0;
6608 * allocate_dir_block --- this function allocates a new directory
6609 * block for a particular inode; this is done if a directory has
6610 * a "hole" in it, or if a directory has a illegal block number
6611 * that was zeroed out and now needs to be replaced.
6613 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
6614 struct problem_context *pctx)
6616 ext2_filsys fs = ctx->fs;
6617 blk_t blk;
6618 char *block;
6619 struct ext2_inode inode;
6621 if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
6622 return 1;
6625 * Read the inode and block bitmaps in; we'll be messing with
6626 * them.
6628 e2fsck_read_bitmaps(ctx);
6631 * First, find a free block
6633 pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6634 if (pctx->errcode) {
6635 pctx->str = "ext2fs_new_block";
6636 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6637 return 1;
6639 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6640 ext2fs_mark_block_bitmap(fs->block_map, blk);
6641 ext2fs_mark_bb_dirty(fs);
6644 * Now let's create the actual data block for the inode
6646 if (db->blockcnt)
6647 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
6648 else
6649 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
6650 EXT2_ROOT_INO, &block);
6652 if (pctx->errcode) {
6653 pctx->str = "ext2fs_new_dir_block";
6654 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6655 return 1;
6658 pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
6659 ext2fs_free_mem(&block);
6660 if (pctx->errcode) {
6661 pctx->str = "ext2fs_write_dir_block";
6662 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6663 return 1;
6667 * Update the inode block count
6669 e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
6670 inode.i_blocks += fs->blocksize / 512;
6671 if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
6672 inode.i_size = (db->blockcnt+1) * fs->blocksize;
6673 e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
6676 * Finally, update the block pointers for the inode
6678 db->blk = blk;
6679 pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
6680 0, update_dir_block, db);
6681 if (pctx->errcode) {
6682 pctx->str = "ext2fs_block_iterate";
6683 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6684 return 1;
6687 return 0;
6691 * This is a helper function for allocate_dir_block().
6693 static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
6694 blk_t *block_nr,
6695 e2_blkcnt_t blockcnt,
6696 blk_t ref_block FSCK_ATTR((unused)),
6697 int ref_offset FSCK_ATTR((unused)),
6698 void *priv_data)
6700 struct ext2_db_entry *db;
6702 db = (struct ext2_db_entry *) priv_data;
6703 if (db->blockcnt == (int) blockcnt) {
6704 *block_nr = db->blk;
6705 return BLOCK_CHANGED;
6707 return 0;
6711 * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
6713 * Pass #3 assures that all directories are connected to the
6714 * filesystem tree, using the following algorithm:
6716 * First, the root directory is checked to make sure it exists; if
6717 * not, e2fsck will offer to create a new one. It is then marked as
6718 * "done".
6720 * Then, pass3 interates over all directory inodes; for each directory
6721 * it attempts to trace up the filesystem tree, using dirinfo.parent
6722 * until it reaches a directory which has been marked "done". If it
6723 * cannot do so, then the directory must be disconnected, and e2fsck
6724 * will offer to reconnect it to /lost+found. While it is chasing
6725 * parent pointers up the filesystem tree, if pass3 sees a directory
6726 * twice, then it has detected a filesystem loop, and it will again
6727 * offer to reconnect the directory to /lost+found in to break the
6728 * filesystem loop.
6730 * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
6731 * reconnect inodes to /lost+found; this subroutine is also used by
6732 * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which
6733 * is responsible for creating /lost+found if it does not exist.
6735 * Pass 3 frees the following data structures:
6736 * - The dirinfo directory information cache.
6739 static void check_root(e2fsck_t ctx);
6740 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6741 struct problem_context *pctx);
6742 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
6744 static ext2fs_inode_bitmap inode_loop_detect;
6745 static ext2fs_inode_bitmap inode_done_map;
6747 static void e2fsck_pass3(e2fsck_t ctx)
6749 ext2_filsys fs = ctx->fs;
6750 int i;
6751 struct problem_context pctx;
6752 struct dir_info *dir;
6753 unsigned long maxdirs, count;
6755 clear_problem_context(&pctx);
6757 /* Pass 3 */
6759 if (!(ctx->options & E2F_OPT_PREEN))
6760 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
6763 * Allocate some bitmaps to do loop detection.
6765 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
6766 &inode_done_map);
6767 if (pctx.errcode) {
6768 pctx.num = 2;
6769 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
6770 ctx->flags |= E2F_FLAG_ABORT;
6771 goto abort_exit;
6773 check_root(ctx);
6774 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6775 goto abort_exit;
6777 ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
6779 maxdirs = e2fsck_get_num_dirinfo(ctx);
6780 count = 1;
6782 if (ctx->progress)
6783 if ((ctx->progress)(ctx, 3, 0, maxdirs))
6784 goto abort_exit;
6786 for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
6787 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6788 goto abort_exit;
6789 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
6790 goto abort_exit;
6791 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
6792 if (check_directory(ctx, dir, &pctx))
6793 goto abort_exit;
6797 * Force the creation of /lost+found if not present
6799 if ((ctx->flags & E2F_OPT_READONLY) == 0)
6800 e2fsck_get_lost_and_found(ctx, 1);
6803 * If there are any directories that need to be indexed or
6804 * optimized, do it here.
6806 e2fsck_rehash_directories(ctx);
6808 abort_exit:
6809 e2fsck_free_dir_info(ctx);
6810 ext2fs_free_inode_bitmap(inode_loop_detect);
6811 inode_loop_detect = 0;
6812 ext2fs_free_inode_bitmap(inode_done_map);
6813 inode_done_map = 0;
6817 * This makes sure the root inode is present; if not, we ask if the
6818 * user wants us to create it. Not creating it is a fatal error.
6820 static void check_root(e2fsck_t ctx)
6822 ext2_filsys fs = ctx->fs;
6823 blk_t blk;
6824 struct ext2_inode inode;
6825 char * block;
6826 struct problem_context pctx;
6828 clear_problem_context(&pctx);
6830 if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
6832 * If the root inode is not a directory, die here. The
6833 * user must have answered 'no' in pass1 when we
6834 * offered to clear it.
6836 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6837 EXT2_ROOT_INO))) {
6838 fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
6839 ctx->flags |= E2F_FLAG_ABORT;
6841 return;
6844 if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
6845 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
6846 ctx->flags |= E2F_FLAG_ABORT;
6847 return;
6850 e2fsck_read_bitmaps(ctx);
6853 * First, find a free block
6855 pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6856 if (pctx.errcode) {
6857 pctx.str = "ext2fs_new_block";
6858 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6859 ctx->flags |= E2F_FLAG_ABORT;
6860 return;
6862 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6863 ext2fs_mark_block_bitmap(fs->block_map, blk);
6864 ext2fs_mark_bb_dirty(fs);
6867 * Now let's create the actual data block for the inode
6869 pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
6870 &block);
6871 if (pctx.errcode) {
6872 pctx.str = "ext2fs_new_dir_block";
6873 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6874 ctx->flags |= E2F_FLAG_ABORT;
6875 return;
6878 pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
6879 if (pctx.errcode) {
6880 pctx.str = "ext2fs_write_dir_block";
6881 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6882 ctx->flags |= E2F_FLAG_ABORT;
6883 return;
6885 ext2fs_free_mem(&block);
6888 * Set up the inode structure
6890 memset(&inode, 0, sizeof(inode));
6891 inode.i_mode = 040755;
6892 inode.i_size = fs->blocksize;
6893 inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
6894 inode.i_links_count = 2;
6895 inode.i_blocks = fs->blocksize / 512;
6896 inode.i_block[0] = blk;
6899 * Write out the inode.
6901 pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
6902 if (pctx.errcode) {
6903 pctx.str = "ext2fs_write_inode";
6904 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6905 ctx->flags |= E2F_FLAG_ABORT;
6906 return;
6910 * Miscellaneous bookkeeping...
6912 e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
6913 ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
6914 ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
6916 ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
6917 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
6918 ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
6919 ext2fs_mark_ib_dirty(fs);
6923 * This subroutine is responsible for making sure that a particular
6924 * directory is connected to the root; if it isn't we trace it up as
6925 * far as we can go, and then offer to connect the resulting parent to
6926 * the lost+found. We have to do loop detection; if we ever discover
6927 * a loop, we treat that as a disconnected directory and offer to
6928 * reparent it to lost+found.
6930 * However, loop detection is expensive, because for very large
6931 * filesystems, the inode_loop_detect bitmap is huge, and clearing it
6932 * is non-trivial. Loops in filesystems are also a rare error case,
6933 * and we shouldn't optimize for error cases. So we try two passes of
6934 * the algorithm. The first time, we ignore loop detection and merely
6935 * increment a counter; if the counter exceeds some extreme threshold,
6936 * then we try again with the loop detection bitmap enabled.
6938 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6939 struct problem_context *pctx)
6941 ext2_filsys fs = ctx->fs;
6942 struct dir_info *p = dir;
6943 int loop_pass = 0, parent_count = 0;
6945 if (!p)
6946 return 0;
6948 while (1) {
6950 * Mark this inode as being "done"; by the time we
6951 * return from this function, the inode we either be
6952 * verified as being connected to the directory tree,
6953 * or we will have offered to reconnect this to
6954 * lost+found.
6956 * If it was marked done already, then we've reached a
6957 * parent we've already checked.
6959 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
6960 break;
6963 * If this directory doesn't have a parent, or we've
6964 * seen the parent once already, then offer to
6965 * reparent it to lost+found
6967 if (!p->parent ||
6968 (loop_pass &&
6969 (ext2fs_test_inode_bitmap(inode_loop_detect,
6970 p->parent)))) {
6971 pctx->ino = p->ino;
6972 if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
6973 if (e2fsck_reconnect_file(ctx, pctx->ino))
6974 ext2fs_unmark_valid(fs);
6975 else {
6976 p = e2fsck_get_dir_info(ctx, pctx->ino);
6977 p->parent = ctx->lost_and_found;
6978 fix_dotdot(ctx, p, ctx->lost_and_found);
6981 break;
6983 p = e2fsck_get_dir_info(ctx, p->parent);
6984 if (!p) {
6985 fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
6986 return 0;
6988 if (loop_pass) {
6989 ext2fs_mark_inode_bitmap(inode_loop_detect,
6990 p->ino);
6991 } else if (parent_count++ > 2048) {
6993 * If we've run into a path depth that's
6994 * greater than 2048, try again with the inode
6995 * loop bitmap turned on and start from the
6996 * top.
6998 loop_pass = 1;
6999 if (inode_loop_detect)
7000 ext2fs_clear_inode_bitmap(inode_loop_detect);
7001 else {
7002 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
7003 if (pctx->errcode) {
7004 pctx->num = 1;
7005 fix_problem(ctx,
7006 PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
7007 ctx->flags |= E2F_FLAG_ABORT;
7008 return -1;
7011 p = dir;
7016 * Make sure that .. and the parent directory are the same;
7017 * offer to fix it if not.
7019 if (dir->parent != dir->dotdot) {
7020 pctx->ino = dir->ino;
7021 pctx->ino2 = dir->dotdot;
7022 pctx->dir = dir->parent;
7023 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
7024 fix_dotdot(ctx, dir, dir->parent);
7026 return 0;
7030 * This routine gets the lost_and_found inode, making it a directory
7031 * if necessary
7033 ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
7035 ext2_filsys fs = ctx->fs;
7036 ext2_ino_t ino;
7037 blk_t blk;
7038 errcode_t retval;
7039 struct ext2_inode inode;
7040 char * block;
7041 static const char name[] = "lost+found";
7042 struct problem_context pctx;
7043 struct dir_info *dirinfo;
7045 if (ctx->lost_and_found)
7046 return ctx->lost_and_found;
7048 clear_problem_context(&pctx);
7050 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
7051 sizeof(name)-1, 0, &ino);
7052 if (retval && !fix)
7053 return 0;
7054 if (!retval) {
7055 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
7056 ctx->lost_and_found = ino;
7057 return ino;
7060 /* Lost+found isn't a directory! */
7061 if (!fix)
7062 return 0;
7063 pctx.ino = ino;
7064 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
7065 return 0;
7067 /* OK, unlink the old /lost+found file. */
7068 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
7069 if (pctx.errcode) {
7070 pctx.str = "ext2fs_unlink";
7071 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7072 return 0;
7074 dirinfo = e2fsck_get_dir_info(ctx, ino);
7075 if (dirinfo)
7076 dirinfo->parent = 0;
7077 e2fsck_adjust_inode_count(ctx, ino, -1);
7078 } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
7079 pctx.errcode = retval;
7080 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
7082 if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
7083 return 0;
7086 * Read the inode and block bitmaps in; we'll be messing with
7087 * them.
7089 e2fsck_read_bitmaps(ctx);
7092 * First, find a free block
7094 retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7095 if (retval) {
7096 pctx.errcode = retval;
7097 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
7098 return 0;
7100 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7101 ext2fs_block_alloc_stats(fs, blk, +1);
7104 * Next find a free inode.
7106 retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
7107 ctx->inode_used_map, &ino);
7108 if (retval) {
7109 pctx.errcode = retval;
7110 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
7111 return 0;
7113 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
7114 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
7115 ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
7118 * Now let's create the actual data block for the inode
7120 retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
7121 if (retval) {
7122 pctx.errcode = retval;
7123 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
7124 return 0;
7127 retval = ext2fs_write_dir_block(fs, blk, block);
7128 ext2fs_free_mem(&block);
7129 if (retval) {
7130 pctx.errcode = retval;
7131 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
7132 return 0;
7136 * Set up the inode structure
7138 memset(&inode, 0, sizeof(inode));
7139 inode.i_mode = 040700;
7140 inode.i_size = fs->blocksize;
7141 inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
7142 inode.i_links_count = 2;
7143 inode.i_blocks = fs->blocksize / 512;
7144 inode.i_block[0] = blk;
7147 * Next, write out the inode.
7149 pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
7150 if (pctx.errcode) {
7151 pctx.str = "ext2fs_write_inode";
7152 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7153 return 0;
7156 * Finally, create the directory link
7158 pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
7159 if (pctx.errcode) {
7160 pctx.str = "ext2fs_link";
7161 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7162 return 0;
7166 * Miscellaneous bookkeeping that needs to be kept straight.
7168 e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
7169 e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
7170 ext2fs_icount_store(ctx->inode_count, ino, 2);
7171 ext2fs_icount_store(ctx->inode_link_info, ino, 2);
7172 ctx->lost_and_found = ino;
7173 return ino;
7177 * This routine will connect a file to lost+found
7179 int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
7181 ext2_filsys fs = ctx->fs;
7182 errcode_t retval;
7183 char name[80];
7184 struct problem_context pctx;
7185 struct ext2_inode inode;
7186 int file_type = 0;
7188 clear_problem_context(&pctx);
7189 pctx.ino = ino;
7191 if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
7192 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
7193 ctx->bad_lost_and_found++;
7195 if (ctx->bad_lost_and_found) {
7196 fix_problem(ctx, PR_3_NO_LPF, &pctx);
7197 return 1;
7200 sprintf(name, "#%u", ino);
7201 if (ext2fs_read_inode(fs, ino, &inode) == 0)
7202 file_type = ext2_file_type(inode.i_mode);
7203 retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
7204 if (retval == EXT2_ET_DIR_NO_SPACE) {
7205 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
7206 return 1;
7207 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
7208 1, 0);
7209 if (retval) {
7210 pctx.errcode = retval;
7211 fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
7212 return 1;
7214 retval = ext2fs_link(fs, ctx->lost_and_found, name,
7215 ino, file_type);
7217 if (retval) {
7218 pctx.errcode = retval;
7219 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
7220 return 1;
7222 e2fsck_adjust_inode_count(ctx, ino, 1);
7224 return 0;
7228 * Utility routine to adjust the inode counts on an inode.
7230 errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
7232 ext2_filsys fs = ctx->fs;
7233 errcode_t retval;
7234 struct ext2_inode inode;
7236 if (!ino)
7237 return 0;
7239 retval = ext2fs_read_inode(fs, ino, &inode);
7240 if (retval)
7241 return retval;
7243 if (adj == 1) {
7244 ext2fs_icount_increment(ctx->inode_count, ino, 0);
7245 if (inode.i_links_count == (__u16) ~0)
7246 return 0;
7247 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
7248 inode.i_links_count++;
7249 } else if (adj == -1) {
7250 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
7251 if (inode.i_links_count == 0)
7252 return 0;
7253 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
7254 inode.i_links_count--;
7257 retval = ext2fs_write_inode(fs, ino, &inode);
7258 if (retval)
7259 return retval;
7261 return 0;
7265 * Fix parent --- this routine fixes up the parent of a directory.
7267 struct fix_dotdot_struct {
7268 ext2_filsys fs;
7269 ext2_ino_t parent;
7270 int done;
7271 e2fsck_t ctx;
7274 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
7275 int offset FSCK_ATTR((unused)),
7276 int blocksize FSCK_ATTR((unused)),
7277 char *buf FSCK_ATTR((unused)),
7278 void *priv_data)
7280 struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
7281 errcode_t retval;
7282 struct problem_context pctx;
7284 if ((dirent->name_len & 0xFF) != 2)
7285 return 0;
7286 if (strncmp(dirent->name, "..", 2))
7287 return 0;
7289 clear_problem_context(&pctx);
7291 retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
7292 if (retval) {
7293 pctx.errcode = retval;
7294 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7296 retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
7297 if (retval) {
7298 pctx.errcode = retval;
7299 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7301 dirent->inode = fp->parent;
7303 fp->done++;
7304 return DIRENT_ABORT | DIRENT_CHANGED;
7307 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
7309 ext2_filsys fs = ctx->fs;
7310 errcode_t retval;
7311 struct fix_dotdot_struct fp;
7312 struct problem_context pctx;
7314 fp.fs = fs;
7315 fp.parent = parent;
7316 fp.done = 0;
7317 fp.ctx = ctx;
7319 retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
7320 0, fix_dotdot_proc, &fp);
7321 if (retval || !fp.done) {
7322 clear_problem_context(&pctx);
7323 pctx.ino = dir->ino;
7324 pctx.errcode = retval;
7325 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
7326 PR_3_FIX_PARENT_NOFIND, &pctx);
7327 ext2fs_unmark_valid(fs);
7329 dir->dotdot = parent;
7333 * These routines are responsible for expanding a /lost+found if it is
7334 * too small.
7337 struct expand_dir_struct {
7338 int num;
7339 int guaranteed_size;
7340 int newblocks;
7341 int last_block;
7342 errcode_t err;
7343 e2fsck_t ctx;
7346 static int expand_dir_proc(ext2_filsys fs,
7347 blk_t *blocknr,
7348 e2_blkcnt_t blockcnt,
7349 blk_t ref_block FSCK_ATTR((unused)),
7350 int ref_offset FSCK_ATTR((unused)),
7351 void *priv_data)
7353 struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
7354 blk_t new_blk;
7355 static blk_t last_blk = 0;
7356 char *block;
7357 errcode_t retval;
7358 e2fsck_t ctx;
7360 ctx = es->ctx;
7362 if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
7363 return BLOCK_ABORT;
7365 if (blockcnt > 0)
7366 es->last_block = blockcnt;
7367 if (*blocknr) {
7368 last_blk = *blocknr;
7369 return 0;
7371 retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
7372 &new_blk);
7373 if (retval) {
7374 es->err = retval;
7375 return BLOCK_ABORT;
7377 if (blockcnt > 0) {
7378 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
7379 if (retval) {
7380 es->err = retval;
7381 return BLOCK_ABORT;
7383 es->num--;
7384 retval = ext2fs_write_dir_block(fs, new_blk, block);
7385 } else {
7386 retval = ext2fs_get_mem(fs->blocksize, &block);
7387 if (retval) {
7388 es->err = retval;
7389 return BLOCK_ABORT;
7391 memset(block, 0, fs->blocksize);
7392 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
7394 if (retval) {
7395 es->err = retval;
7396 return BLOCK_ABORT;
7398 ext2fs_free_mem(&block);
7399 *blocknr = new_blk;
7400 ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
7401 ext2fs_block_alloc_stats(fs, new_blk, +1);
7402 es->newblocks++;
7404 if (es->num == 0)
7405 return (BLOCK_CHANGED | BLOCK_ABORT);
7406 else
7407 return BLOCK_CHANGED;
7410 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
7411 int num, int guaranteed_size)
7413 ext2_filsys fs = ctx->fs;
7414 errcode_t retval;
7415 struct expand_dir_struct es;
7416 struct ext2_inode inode;
7418 if (!(fs->flags & EXT2_FLAG_RW))
7419 return EXT2_ET_RO_FILSYS;
7422 * Read the inode and block bitmaps in; we'll be messing with
7423 * them.
7425 e2fsck_read_bitmaps(ctx);
7427 retval = ext2fs_check_directory(fs, dir);
7428 if (retval)
7429 return retval;
7431 es.num = num;
7432 es.guaranteed_size = guaranteed_size;
7433 es.last_block = 0;
7434 es.err = 0;
7435 es.newblocks = 0;
7436 es.ctx = ctx;
7438 retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
7439 0, expand_dir_proc, &es);
7441 if (es.err)
7442 return es.err;
7445 * Update the size and block count fields in the inode.
7447 retval = ext2fs_read_inode(fs, dir, &inode);
7448 if (retval)
7449 return retval;
7451 inode.i_size = (es.last_block + 1) * fs->blocksize;
7452 inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
7454 e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
7456 return 0;
7460 * pass4.c -- pass #4 of e2fsck: Check reference counts
7462 * Pass 4 frees the following data structures:
7463 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
7467 * This routine is called when an inode is not connected to the
7468 * directory tree.
7470 * This subroutine returns 1 then the caller shouldn't bother with the
7471 * rest of the pass 4 tests.
7473 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
7475 ext2_filsys fs = ctx->fs;
7476 struct ext2_inode inode;
7477 struct problem_context pctx;
7479 e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
7480 clear_problem_context(&pctx);
7481 pctx.ino = i;
7482 pctx.inode = &inode;
7485 * Offer to delete any zero-length files that does not have
7486 * blocks. If there is an EA block, it might have useful
7487 * information, so we won't prompt to delete it, but let it be
7488 * reconnected to lost+found.
7490 if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
7491 LINUX_S_ISDIR(inode.i_mode))) {
7492 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
7493 ext2fs_icount_store(ctx->inode_link_info, i, 0);
7494 inode.i_links_count = 0;
7495 inode.i_dtime = time(NULL);
7496 e2fsck_write_inode(ctx, i, &inode,
7497 "disconnect_inode");
7499 * Fix up the bitmaps...
7501 e2fsck_read_bitmaps(ctx);
7502 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
7503 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
7504 ext2fs_inode_alloc_stats2(fs, i, -1,
7505 LINUX_S_ISDIR(inode.i_mode));
7506 return 0;
7511 * Prompt to reconnect.
7513 if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7514 if (e2fsck_reconnect_file(ctx, i))
7515 ext2fs_unmark_valid(fs);
7516 } else {
7518 * If we don't attach the inode, then skip the
7519 * i_links_test since there's no point in trying to
7520 * force i_links_count to zero.
7522 ext2fs_unmark_valid(fs);
7523 return 1;
7525 return 0;
7529 static void e2fsck_pass4(e2fsck_t ctx)
7531 ext2_filsys fs = ctx->fs;
7532 ext2_ino_t i;
7533 struct ext2_inode inode;
7534 struct problem_context pctx;
7535 __u16 link_count, link_counted;
7536 char *buf = NULL;
7537 int group, maxgroup;
7539 /* Pass 4 */
7541 clear_problem_context(&pctx);
7543 if (!(ctx->options & E2F_OPT_PREEN))
7544 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
7546 group = 0;
7547 maxgroup = fs->group_desc_count;
7548 if (ctx->progress)
7549 if ((ctx->progress)(ctx, 4, 0, maxgroup))
7550 return;
7552 for (i=1; i <= fs->super->s_inodes_count; i++) {
7553 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7554 return;
7555 if ((i % fs->super->s_inodes_per_group) == 0) {
7556 group++;
7557 if (ctx->progress)
7558 if ((ctx->progress)(ctx, 4, group, maxgroup))
7559 return;
7561 if (i == EXT2_BAD_INO ||
7562 (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
7563 continue;
7564 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
7565 (ctx->inode_imagic_map &&
7566 ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
7567 continue;
7568 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
7569 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
7570 if (link_counted == 0) {
7571 if (!buf)
7572 buf = e2fsck_allocate_memory(ctx,
7573 fs->blocksize, "bad_inode buffer");
7574 if (e2fsck_process_bad_inode(ctx, 0, i, buf))
7575 continue;
7576 if (disconnect_inode(ctx, i))
7577 continue;
7578 ext2fs_icount_fetch(ctx->inode_link_info, i,
7579 &link_count);
7580 ext2fs_icount_fetch(ctx->inode_count, i,
7581 &link_counted);
7583 if (link_counted != link_count) {
7584 e2fsck_read_inode(ctx, i, &inode, "pass4");
7585 pctx.ino = i;
7586 pctx.inode = &inode;
7587 if (link_count != inode.i_links_count) {
7588 pctx.num = link_count;
7589 fix_problem(ctx,
7590 PR_4_INCONSISTENT_COUNT, &pctx);
7592 pctx.num = link_counted;
7593 if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
7594 inode.i_links_count = link_counted;
7595 e2fsck_write_inode(ctx, i, &inode, "pass4");
7599 ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
7600 ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
7601 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
7602 ctx->inode_imagic_map = 0;
7603 ext2fs_free_mem(&buf);
7607 * pass5.c --- check block and inode bitmaps against on-disk bitmaps
7610 #define NO_BLK ((blk_t) -1)
7612 static void print_bitmap_problem(e2fsck_t ctx, int problem,
7613 struct problem_context *pctx)
7615 switch (problem) {
7616 case PR_5_BLOCK_UNUSED:
7617 if (pctx->blk == pctx->blk2)
7618 pctx->blk2 = 0;
7619 else
7620 problem = PR_5_BLOCK_RANGE_UNUSED;
7621 break;
7622 case PR_5_BLOCK_USED:
7623 if (pctx->blk == pctx->blk2)
7624 pctx->blk2 = 0;
7625 else
7626 problem = PR_5_BLOCK_RANGE_USED;
7627 break;
7628 case PR_5_INODE_UNUSED:
7629 if (pctx->ino == pctx->ino2)
7630 pctx->ino2 = 0;
7631 else
7632 problem = PR_5_INODE_RANGE_UNUSED;
7633 break;
7634 case PR_5_INODE_USED:
7635 if (pctx->ino == pctx->ino2)
7636 pctx->ino2 = 0;
7637 else
7638 problem = PR_5_INODE_RANGE_USED;
7639 break;
7641 fix_problem(ctx, problem, pctx);
7642 pctx->blk = pctx->blk2 = NO_BLK;
7643 pctx->ino = pctx->ino2 = 0;
7646 static void check_block_bitmaps(e2fsck_t ctx)
7648 ext2_filsys fs = ctx->fs;
7649 blk_t i;
7650 int *free_array;
7651 int group = 0;
7652 unsigned int blocks = 0;
7653 unsigned int free_blocks = 0;
7654 int group_free = 0;
7655 int actual, bitmap;
7656 struct problem_context pctx;
7657 int problem, save_problem, fixit, had_problem;
7658 errcode_t retval;
7660 clear_problem_context(&pctx);
7661 free_array = (int *) e2fsck_allocate_memory(ctx,
7662 fs->group_desc_count * sizeof(int), "free block count array");
7664 if ((fs->super->s_first_data_block <
7665 ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
7666 (fs->super->s_blocks_count-1 >
7667 ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
7668 pctx.num = 1;
7669 pctx.blk = fs->super->s_first_data_block;
7670 pctx.blk2 = fs->super->s_blocks_count -1;
7671 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
7672 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
7673 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7675 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7676 return;
7679 if ((fs->super->s_first_data_block <
7680 ext2fs_get_block_bitmap_start(fs->block_map)) ||
7681 (fs->super->s_blocks_count-1 >
7682 ext2fs_get_block_bitmap_end(fs->block_map))) {
7683 pctx.num = 2;
7684 pctx.blk = fs->super->s_first_data_block;
7685 pctx.blk2 = fs->super->s_blocks_count -1;
7686 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
7687 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
7688 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7690 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7691 return;
7694 redo_counts:
7695 had_problem = 0;
7696 save_problem = 0;
7697 pctx.blk = pctx.blk2 = NO_BLK;
7698 for (i = fs->super->s_first_data_block;
7699 i < fs->super->s_blocks_count;
7700 i++) {
7701 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
7702 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
7704 if (actual == bitmap)
7705 goto do_counts;
7707 if (!actual && bitmap) {
7709 * Block not used, but marked in use in the bitmap.
7711 problem = PR_5_BLOCK_UNUSED;
7712 } else {
7714 * Block used, but not marked in use in the bitmap.
7716 problem = PR_5_BLOCK_USED;
7718 if (pctx.blk == NO_BLK) {
7719 pctx.blk = pctx.blk2 = i;
7720 save_problem = problem;
7721 } else {
7722 if ((problem == save_problem) &&
7723 (pctx.blk2 == i-1))
7724 pctx.blk2++;
7725 else {
7726 print_bitmap_problem(ctx, save_problem, &pctx);
7727 pctx.blk = pctx.blk2 = i;
7728 save_problem = problem;
7731 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7732 had_problem++;
7734 do_counts:
7735 if (!bitmap) {
7736 group_free++;
7737 free_blocks++;
7739 blocks ++;
7740 if ((blocks == fs->super->s_blocks_per_group) ||
7741 (i == fs->super->s_blocks_count-1)) {
7742 free_array[group] = group_free;
7743 group ++;
7744 blocks = 0;
7745 group_free = 0;
7746 if (ctx->progress)
7747 if ((ctx->progress)(ctx, 5, group,
7748 fs->group_desc_count*2))
7749 return;
7752 if (pctx.blk != NO_BLK)
7753 print_bitmap_problem(ctx, save_problem, &pctx);
7754 if (had_problem)
7755 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
7756 else
7757 fixit = -1;
7758 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7760 if (fixit == 1) {
7761 ext2fs_free_block_bitmap(fs->block_map);
7762 retval = ext2fs_copy_bitmap(ctx->block_found_map,
7763 &fs->block_map);
7764 if (retval) {
7765 clear_problem_context(&pctx);
7766 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
7767 ctx->flags |= E2F_FLAG_ABORT;
7768 return;
7770 ext2fs_set_bitmap_padding(fs->block_map);
7771 ext2fs_mark_bb_dirty(fs);
7773 /* Redo the counts */
7774 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
7775 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7776 goto redo_counts;
7777 } else if (fixit == 0)
7778 ext2fs_unmark_valid(fs);
7780 for (i = 0; i < fs->group_desc_count; i++) {
7781 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
7782 pctx.group = i;
7783 pctx.blk = fs->group_desc[i].bg_free_blocks_count;
7784 pctx.blk2 = free_array[i];
7786 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
7787 &pctx)) {
7788 fs->group_desc[i].bg_free_blocks_count =
7789 free_array[i];
7790 ext2fs_mark_super_dirty(fs);
7791 } else
7792 ext2fs_unmark_valid(fs);
7795 if (free_blocks != fs->super->s_free_blocks_count) {
7796 pctx.group = 0;
7797 pctx.blk = fs->super->s_free_blocks_count;
7798 pctx.blk2 = free_blocks;
7800 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
7801 fs->super->s_free_blocks_count = free_blocks;
7802 ext2fs_mark_super_dirty(fs);
7803 } else
7804 ext2fs_unmark_valid(fs);
7806 ext2fs_free_mem(&free_array);
7809 static void check_inode_bitmaps(e2fsck_t ctx)
7811 ext2_filsys fs = ctx->fs;
7812 ext2_ino_t i;
7813 unsigned int free_inodes = 0;
7814 int group_free = 0;
7815 int dirs_count = 0;
7816 int group = 0;
7817 unsigned int inodes = 0;
7818 int *free_array;
7819 int *dir_array;
7820 int actual, bitmap;
7821 errcode_t retval;
7822 struct problem_context pctx;
7823 int problem, save_problem, fixit, had_problem;
7825 clear_problem_context(&pctx);
7826 free_array = (int *) e2fsck_allocate_memory(ctx,
7827 fs->group_desc_count * sizeof(int), "free inode count array");
7829 dir_array = (int *) e2fsck_allocate_memory(ctx,
7830 fs->group_desc_count * sizeof(int), "directory count array");
7832 if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
7833 (fs->super->s_inodes_count >
7834 ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
7835 pctx.num = 3;
7836 pctx.blk = 1;
7837 pctx.blk2 = fs->super->s_inodes_count;
7838 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
7839 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
7840 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7842 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7843 return;
7845 if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
7846 (fs->super->s_inodes_count >
7847 ext2fs_get_inode_bitmap_end(fs->inode_map))) {
7848 pctx.num = 4;
7849 pctx.blk = 1;
7850 pctx.blk2 = fs->super->s_inodes_count;
7851 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
7852 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
7853 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7855 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7856 return;
7859 redo_counts:
7860 had_problem = 0;
7861 save_problem = 0;
7862 pctx.ino = pctx.ino2 = 0;
7863 for (i = 1; i <= fs->super->s_inodes_count; i++) {
7864 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
7865 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
7867 if (actual == bitmap)
7868 goto do_counts;
7870 if (!actual && bitmap) {
7872 * Inode wasn't used, but marked in bitmap
7874 problem = PR_5_INODE_UNUSED;
7875 } else /* if (actual && !bitmap) */ {
7877 * Inode used, but not in bitmap
7879 problem = PR_5_INODE_USED;
7881 if (pctx.ino == 0) {
7882 pctx.ino = pctx.ino2 = i;
7883 save_problem = problem;
7884 } else {
7885 if ((problem == save_problem) &&
7886 (pctx.ino2 == i-1))
7887 pctx.ino2++;
7888 else {
7889 print_bitmap_problem(ctx, save_problem, &pctx);
7890 pctx.ino = pctx.ino2 = i;
7891 save_problem = problem;
7894 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7895 had_problem++;
7897 do_counts:
7898 if (!bitmap) {
7899 group_free++;
7900 free_inodes++;
7901 } else {
7902 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
7903 dirs_count++;
7905 inodes++;
7906 if ((inodes == fs->super->s_inodes_per_group) ||
7907 (i == fs->super->s_inodes_count)) {
7908 free_array[group] = group_free;
7909 dir_array[group] = dirs_count;
7910 group ++;
7911 inodes = 0;
7912 group_free = 0;
7913 dirs_count = 0;
7914 if (ctx->progress)
7915 if ((ctx->progress)(ctx, 5,
7916 group + fs->group_desc_count,
7917 fs->group_desc_count*2))
7918 return;
7921 if (pctx.ino)
7922 print_bitmap_problem(ctx, save_problem, &pctx);
7924 if (had_problem)
7925 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
7926 else
7927 fixit = -1;
7928 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7930 if (fixit == 1) {
7931 ext2fs_free_inode_bitmap(fs->inode_map);
7932 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
7933 &fs->inode_map);
7934 if (retval) {
7935 clear_problem_context(&pctx);
7936 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
7937 ctx->flags |= E2F_FLAG_ABORT;
7938 return;
7940 ext2fs_set_bitmap_padding(fs->inode_map);
7941 ext2fs_mark_ib_dirty(fs);
7943 /* redo counts */
7944 inodes = 0; free_inodes = 0; group_free = 0;
7945 dirs_count = 0; group = 0;
7946 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7947 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
7948 goto redo_counts;
7949 } else if (fixit == 0)
7950 ext2fs_unmark_valid(fs);
7952 for (i = 0; i < fs->group_desc_count; i++) {
7953 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
7954 pctx.group = i;
7955 pctx.ino = fs->group_desc[i].bg_free_inodes_count;
7956 pctx.ino2 = free_array[i];
7957 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
7958 &pctx)) {
7959 fs->group_desc[i].bg_free_inodes_count =
7960 free_array[i];
7961 ext2fs_mark_super_dirty(fs);
7962 } else
7963 ext2fs_unmark_valid(fs);
7965 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
7966 pctx.group = i;
7967 pctx.ino = fs->group_desc[i].bg_used_dirs_count;
7968 pctx.ino2 = dir_array[i];
7970 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
7971 &pctx)) {
7972 fs->group_desc[i].bg_used_dirs_count =
7973 dir_array[i];
7974 ext2fs_mark_super_dirty(fs);
7975 } else
7976 ext2fs_unmark_valid(fs);
7979 if (free_inodes != fs->super->s_free_inodes_count) {
7980 pctx.group = -1;
7981 pctx.ino = fs->super->s_free_inodes_count;
7982 pctx.ino2 = free_inodes;
7984 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
7985 fs->super->s_free_inodes_count = free_inodes;
7986 ext2fs_mark_super_dirty(fs);
7987 } else
7988 ext2fs_unmark_valid(fs);
7990 ext2fs_free_mem(&free_array);
7991 ext2fs_free_mem(&dir_array);
7994 static void check_inode_end(e2fsck_t ctx)
7996 ext2_filsys fs = ctx->fs;
7997 ext2_ino_t end, save_inodes_count, i;
7998 struct problem_context pctx;
8000 clear_problem_context(&pctx);
8002 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
8003 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
8004 &save_inodes_count);
8005 if (pctx.errcode) {
8006 pctx.num = 1;
8007 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8008 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8009 return;
8011 if (save_inodes_count == end)
8012 return;
8014 for (i = save_inodes_count + 1; i <= end; i++) {
8015 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
8016 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
8017 for (i = save_inodes_count + 1; i <= end; i++)
8018 ext2fs_mark_inode_bitmap(fs->inode_map,
8020 ext2fs_mark_ib_dirty(fs);
8021 } else
8022 ext2fs_unmark_valid(fs);
8023 break;
8027 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
8028 save_inodes_count, 0);
8029 if (pctx.errcode) {
8030 pctx.num = 2;
8031 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8032 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8033 return;
8037 static void check_block_end(e2fsck_t ctx)
8039 ext2_filsys fs = ctx->fs;
8040 blk_t end, save_blocks_count, i;
8041 struct problem_context pctx;
8043 clear_problem_context(&pctx);
8045 end = fs->block_map->start +
8046 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
8047 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
8048 &save_blocks_count);
8049 if (pctx.errcode) {
8050 pctx.num = 3;
8051 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8052 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8053 return;
8055 if (save_blocks_count == end)
8056 return;
8058 for (i = save_blocks_count + 1; i <= end; i++) {
8059 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
8060 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
8061 for (i = save_blocks_count + 1; i <= end; i++)
8062 ext2fs_mark_block_bitmap(fs->block_map,
8064 ext2fs_mark_bb_dirty(fs);
8065 } else
8066 ext2fs_unmark_valid(fs);
8067 break;
8071 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
8072 save_blocks_count, 0);
8073 if (pctx.errcode) {
8074 pctx.num = 4;
8075 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8076 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8077 return;
8081 static void e2fsck_pass5(e2fsck_t ctx)
8083 struct problem_context pctx;
8085 /* Pass 5 */
8087 clear_problem_context(&pctx);
8089 if (!(ctx->options & E2F_OPT_PREEN))
8090 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
8092 if (ctx->progress)
8093 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
8094 return;
8096 e2fsck_read_bitmaps(ctx);
8098 check_block_bitmaps(ctx);
8099 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8100 return;
8101 check_inode_bitmaps(ctx);
8102 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8103 return;
8104 check_inode_end(ctx);
8105 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8106 return;
8107 check_block_end(ctx);
8108 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8109 return;
8111 ext2fs_free_inode_bitmap(ctx->inode_used_map);
8112 ctx->inode_used_map = 0;
8113 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
8114 ctx->inode_dir_map = 0;
8115 ext2fs_free_block_bitmap(ctx->block_found_map);
8116 ctx->block_found_map = 0;
8120 * problem.c --- report filesystem problems to the user
8123 #define PR_PREEN_OK 0x000001 /* Don't need to do preenhalt */
8124 #define PR_NO_OK 0x000002 /* If user answers no, don't make fs invalid */
8125 #define PR_NO_DEFAULT 0x000004 /* Default to no */
8126 #define PR_MSG_ONLY 0x000008 /* Print message only */
8128 /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
8130 #define PR_FATAL 0x001000 /* Fatal error */
8131 #define PR_AFTER_CODE 0x002000 /* After asking the first question, */
8132 /* ask another */
8133 #define PR_PREEN_NOMSG 0x004000 /* Don't print a message if we're preening */
8134 #define PR_NOCOLLATE 0x008000 /* Don't collate answers for this latch */
8135 #define PR_NO_NOMSG 0x010000 /* Don't print a message if e2fsck -n */
8136 #define PR_PREEN_NO 0x020000 /* Use No as an answer if preening */
8137 #define PR_PREEN_NOHDR 0x040000 /* Don't print the preen header */
8140 #define PROMPT_NONE 0
8141 #define PROMPT_FIX 1
8142 #define PROMPT_CLEAR 2
8143 #define PROMPT_RELOCATE 3
8144 #define PROMPT_ALLOCATE 4
8145 #define PROMPT_EXPAND 5
8146 #define PROMPT_CONNECT 6
8147 #define PROMPT_CREATE 7
8148 #define PROMPT_SALVAGE 8
8149 #define PROMPT_TRUNCATE 9
8150 #define PROMPT_CLEAR_INODE 10
8151 #define PROMPT_ABORT 11
8152 #define PROMPT_SPLIT 12
8153 #define PROMPT_CONTINUE 13
8154 #define PROMPT_CLONE 14
8155 #define PROMPT_DELETE 15
8156 #define PROMPT_SUPPRESS 16
8157 #define PROMPT_UNLINK 17
8158 #define PROMPT_CLEAR_HTREE 18
8159 #define PROMPT_RECREATE 19
8160 #define PROMPT_NULL 20
8162 struct e2fsck_problem {
8163 problem_t e2p_code;
8164 const char * e2p_description;
8165 char prompt;
8166 int flags;
8167 problem_t second_code;
8170 struct latch_descr {
8171 int latch_code;
8172 problem_t question;
8173 problem_t end_message;
8174 int flags;
8178 * These are the prompts which are used to ask the user if they want
8179 * to fix a problem.
8181 static const char *const prompt[] = {
8182 N_("(no prompt)"), /* 0 */
8183 N_("Fix"), /* 1 */
8184 N_("Clear"), /* 2 */
8185 N_("Relocate"), /* 3 */
8186 N_("Allocate"), /* 4 */
8187 N_("Expand"), /* 5 */
8188 N_("Connect to /lost+found"), /* 6 */
8189 N_("Create"), /* 7 */
8190 N_("Salvage"), /* 8 */
8191 N_("Truncate"), /* 9 */
8192 N_("Clear inode"), /* 10 */
8193 N_("Abort"), /* 11 */
8194 N_("Split"), /* 12 */
8195 N_("Continue"), /* 13 */
8196 N_("Clone multiply-claimed blocks"), /* 14 */
8197 N_("Delete file"), /* 15 */
8198 N_("Suppress messages"),/* 16 */
8199 N_("Unlink"), /* 17 */
8200 N_("Clear HTree index"),/* 18 */
8201 N_("Recreate"), /* 19 */
8202 "", /* 20 */
8206 * These messages are printed when we are preen mode and we will be
8207 * automatically fixing the problem.
8209 static const char *const preen_msg[] = {
8210 N_("(NONE)"), /* 0 */
8211 N_("FIXED"), /* 1 */
8212 N_("CLEARED"), /* 2 */
8213 N_("RELOCATED"), /* 3 */
8214 N_("ALLOCATED"), /* 4 */
8215 N_("EXPANDED"), /* 5 */
8216 N_("RECONNECTED"), /* 6 */
8217 N_("CREATED"), /* 7 */
8218 N_("SALVAGED"), /* 8 */
8219 N_("TRUNCATED"), /* 9 */
8220 N_("INODE CLEARED"), /* 10 */
8221 N_("ABORTED"), /* 11 */
8222 N_("SPLIT"), /* 12 */
8223 N_("CONTINUING"), /* 13 */
8224 N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
8225 N_("FILE DELETED"), /* 15 */
8226 N_("SUPPRESSED"), /* 16 */
8227 N_("UNLINKED"), /* 17 */
8228 N_("HTREE INDEX CLEARED"),/* 18 */
8229 N_("WILL RECREATE"), /* 19 */
8230 "", /* 20 */
8233 static const struct e2fsck_problem problem_table[] = {
8235 /* Pre-Pass 1 errors */
8237 /* Block bitmap not in group */
8238 { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g. (@b %b)\n"),
8239 PROMPT_RELOCATE, PR_LATCH_RELOC },
8241 /* Inode bitmap not in group */
8242 { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g. (@b %b)\n"),
8243 PROMPT_RELOCATE, PR_LATCH_RELOC },
8245 /* Inode table not in group */
8246 { PR_0_ITABLE_NOT_GROUP,
8247 N_("@i table for @g %g is not in @g. (@b %b)\n"
8248 "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
8249 PROMPT_RELOCATE, PR_LATCH_RELOC },
8251 /* Superblock corrupt */
8252 { PR_0_SB_CORRUPT,
8253 N_("\nThe @S could not be read or does not describe a correct ext2\n"
8254 "@f. If the @v is valid and it really contains an ext2\n"
8255 "@f (and not swap or ufs or something else), then the @S\n"
8256 "is corrupt, and you might try running e2fsck with an alternate @S:\n"
8257 " e2fsck -b %S <@v>\n\n"),
8258 PROMPT_NONE, PR_FATAL },
8260 /* Filesystem size is wrong */
8261 { PR_0_FS_SIZE_WRONG,
8262 N_("The @f size (according to the @S) is %b @bs\n"
8263 "The physical size of the @v is %c @bs\n"
8264 "Either the @S or the partition table is likely to be corrupt!\n"),
8265 PROMPT_ABORT, 0 },
8267 /* Fragments not supported */
8268 { PR_0_NO_FRAGMENTS,
8269 N_("@S @b_size = %b, fragsize = %c.\n"
8270 "This version of e2fsck does not support fragment sizes different\n"
8271 "from the @b size.\n"),
8272 PROMPT_NONE, PR_FATAL },
8274 /* Bad blocks_per_group */
8275 { PR_0_BLOCKS_PER_GROUP,
8276 N_("@S @bs_per_group = %b, should have been %c\n"),
8277 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8279 /* Bad first_data_block */
8280 { PR_0_FIRST_DATA_BLOCK,
8281 N_("@S first_data_@b = %b, should have been %c\n"),
8282 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8284 /* Adding UUID to filesystem */
8285 { PR_0_ADD_UUID,
8286 N_("@f did not have a UUID; generating one.\n\n"),
8287 PROMPT_NONE, 0 },
8289 /* Relocate hint */
8290 { PR_0_RELOCATE_HINT,
8291 N_("Note: if several inode or block bitmap blocks or part\n"
8292 "of the inode table require relocation, you may wish to try\n"
8293 "running e2fsck with the '-b %S' option first. The problem\n"
8294 "may lie only with the primary block group descriptors, and\n"
8295 "the backup block group descriptors may be OK.\n\n"),
8296 PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
8298 /* Miscellaneous superblock corruption */
8299 { PR_0_MISC_CORRUPT_SUPER,
8300 N_("Corruption found in @S. (%s = %N).\n"),
8301 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8303 /* Error determing physical device size of filesystem */
8304 { PR_0_GETSIZE_ERROR,
8305 N_("Error determining size of the physical @v: %m\n"),
8306 PROMPT_NONE, PR_FATAL },
8308 /* Inode count in superblock is incorrect */
8309 { PR_0_INODE_COUNT_WRONG,
8310 N_("@i count in @S is %i, @s %j.\n"),
8311 PROMPT_FIX, 0 },
8313 { PR_0_HURD_CLEAR_FILETYPE,
8314 N_("The Hurd does not support the filetype feature.\n"),
8315 PROMPT_CLEAR, 0 },
8317 /* Journal inode is invalid */
8318 { PR_0_JOURNAL_BAD_INODE,
8319 N_("@S has an @n ext3 @j (@i %i).\n"),
8320 PROMPT_CLEAR, PR_PREEN_OK },
8322 /* The external journal has (unsupported) multiple filesystems */
8323 { PR_0_JOURNAL_UNSUPP_MULTIFS,
8324 N_("External @j has multiple @f users (unsupported).\n"),
8325 PROMPT_NONE, PR_FATAL },
8327 /* Can't find external journal */
8328 { PR_0_CANT_FIND_JOURNAL,
8329 N_("Can't find external @j\n"),
8330 PROMPT_NONE, PR_FATAL },
8332 /* External journal has bad superblock */
8333 { PR_0_EXT_JOURNAL_BAD_SUPER,
8334 N_("External @j has bad @S\n"),
8335 PROMPT_NONE, PR_FATAL },
8337 /* Superblock has a bad journal UUID */
8338 { PR_0_JOURNAL_BAD_UUID,
8339 N_("External @j does not support this @f\n"),
8340 PROMPT_NONE, PR_FATAL },
8342 /* Journal has an unknown superblock type */
8343 { PR_0_JOURNAL_UNSUPP_SUPER,
8344 N_("Ext3 @j @S is unknown type %N (unsupported).\n"
8345 "It is likely that your copy of e2fsck is old and/or doesn't "
8346 "support this @j format.\n"
8347 "It is also possible the @j @S is corrupt.\n"),
8348 PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
8350 /* Journal superblock is corrupt */
8351 { PR_0_JOURNAL_BAD_SUPER,
8352 N_("Ext3 @j @S is corrupt.\n"),
8353 PROMPT_FIX, PR_PREEN_OK },
8355 /* Superblock flag should be cleared */
8356 { PR_0_JOURNAL_HAS_JOURNAL,
8357 N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
8358 PROMPT_CLEAR, PR_PREEN_OK },
8360 /* Superblock flag is incorrect */
8361 { PR_0_JOURNAL_RECOVER_SET,
8362 N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
8363 PROMPT_CLEAR, PR_PREEN_OK },
8365 /* Journal has data, but recovery flag is clear */
8366 { PR_0_JOURNAL_RECOVERY_CLEAR,
8367 N_("ext3 recovery flag is clear, but @j has data.\n"),
8368 PROMPT_NONE, 0 },
8370 /* Ask if we should clear the journal */
8371 { PR_0_JOURNAL_RESET_JOURNAL,
8372 N_("Clear @j"),
8373 PROMPT_NULL, PR_PREEN_NOMSG },
8375 /* Ask if we should run the journal anyway */
8376 { PR_0_JOURNAL_RUN,
8377 N_("Run @j anyway"),
8378 PROMPT_NULL, 0 },
8380 /* Run the journal by default */
8381 { PR_0_JOURNAL_RUN_DEFAULT,
8382 N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
8383 PROMPT_NONE, 0 },
8385 /* Clearing orphan inode */
8386 { PR_0_ORPHAN_CLEAR_INODE,
8387 N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
8388 PROMPT_NONE, 0 },
8390 /* Illegal block found in orphaned inode */
8391 { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
8392 N_("@I @b #%B (%b) found in @o @i %i.\n"),
8393 PROMPT_NONE, 0 },
8395 /* Already cleared block found in orphaned inode */
8396 { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
8397 N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
8398 PROMPT_NONE, 0 },
8400 /* Illegal orphan inode in superblock */
8401 { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
8402 N_("@I @o @i %i in @S.\n"),
8403 PROMPT_NONE, 0 },
8405 /* Illegal inode in orphaned inode list */
8406 { PR_0_ORPHAN_ILLEGAL_INODE,
8407 N_("@I @i %i in @o @i list.\n"),
8408 PROMPT_NONE, 0 },
8410 /* Filesystem revision is 0, but feature flags are set */
8411 { PR_0_FS_REV_LEVEL,
8412 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8413 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8415 /* Journal superblock has an unknown read-only feature flag set */
8416 { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
8417 N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
8418 PROMPT_ABORT, 0 },
8420 /* Journal superblock has an unknown incompatible feature flag set */
8421 { PR_0_JOURNAL_UNSUPP_INCOMPAT,
8422 N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
8423 PROMPT_ABORT, 0 },
8425 /* Journal has unsupported version number */
8426 { PR_0_JOURNAL_UNSUPP_VERSION,
8427 N_("@j version not supported by this e2fsck.\n"),
8428 PROMPT_ABORT, 0 },
8430 /* Moving journal to hidden file */
8431 { PR_0_MOVE_JOURNAL,
8432 N_("Moving @j from /%s to hidden @i.\n\n"),
8433 PROMPT_NONE, 0 },
8435 /* Error moving journal to hidden file */
8436 { PR_0_ERR_MOVE_JOURNAL,
8437 N_("Error moving @j: %m\n\n"),
8438 PROMPT_NONE, 0 },
8440 /* Clearing V2 journal superblock */
8441 { PR_0_CLEAR_V2_JOURNAL,
8442 N_("Found @n V2 @j @S fields (from V1 @j).\n"
8443 "Clearing fields beyond the V1 @j @S...\n\n"),
8444 PROMPT_NONE, 0 },
8446 /* Backup journal inode blocks */
8447 { PR_0_BACKUP_JNL,
8448 N_("Backing up @j @i @b information.\n\n"),
8449 PROMPT_NONE, 0 },
8451 /* Reserved blocks w/o resize_inode */
8452 { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
8453 N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
8454 "is %N; @s zero. "),
8455 PROMPT_FIX, 0 },
8457 /* Resize_inode not enabled, but resize inode is non-zero */
8458 { PR_0_CLEAR_RESIZE_INODE,
8459 N_("Resize_@i not enabled, but the resize @i is non-zero. "),
8460 PROMPT_CLEAR, 0 },
8462 /* Resize inode invalid */
8463 { PR_0_RESIZE_INODE_INVALID,
8464 N_("Resize @i not valid. "),
8465 PROMPT_RECREATE, 0 },
8467 /* Pass 1 errors */
8469 /* Pass 1: Checking inodes, blocks, and sizes */
8470 { PR_1_PASS_HEADER,
8471 N_("Pass 1: Checking @is, @bs, and sizes\n"),
8472 PROMPT_NONE, 0 },
8474 /* Root directory is not an inode */
8475 { PR_1_ROOT_NO_DIR, N_("@r is not a @d. "),
8476 PROMPT_CLEAR, 0 },
8478 /* Root directory has dtime set */
8479 { PR_1_ROOT_DTIME,
8480 N_("@r has dtime set (probably due to old mke2fs). "),
8481 PROMPT_FIX, PR_PREEN_OK },
8483 /* Reserved inode has bad mode */
8484 { PR_1_RESERVED_BAD_MODE,
8485 N_("Reserved @i %i (%Q) has @n mode. "),
8486 PROMPT_CLEAR, PR_PREEN_OK },
8488 /* Deleted inode has zero dtime */
8489 { PR_1_ZERO_DTIME,
8490 N_("@D @i %i has zero dtime. "),
8491 PROMPT_FIX, PR_PREEN_OK },
8493 /* Inode in use, but dtime set */
8494 { PR_1_SET_DTIME,
8495 N_("@i %i is in use, but has dtime set. "),
8496 PROMPT_FIX, PR_PREEN_OK },
8498 /* Zero-length directory */
8499 { PR_1_ZERO_LENGTH_DIR,
8500 N_("@i %i is a @z @d. "),
8501 PROMPT_CLEAR, PR_PREEN_OK },
8503 /* Block bitmap conflicts with some other fs block */
8504 { PR_1_BB_CONFLICT,
8505 N_("@g %g's @b @B at %b @C.\n"),
8506 PROMPT_RELOCATE, 0 },
8508 /* Inode bitmap conflicts with some other fs block */
8509 { PR_1_IB_CONFLICT,
8510 N_("@g %g's @i @B at %b @C.\n"),
8511 PROMPT_RELOCATE, 0 },
8513 /* Inode table conflicts with some other fs block */
8514 { PR_1_ITABLE_CONFLICT,
8515 N_("@g %g's @i table at %b @C.\n"),
8516 PROMPT_RELOCATE, 0 },
8518 /* Block bitmap is on a bad block */
8519 { PR_1_BB_BAD_BLOCK,
8520 N_("@g %g's @b @B (%b) is bad. "),
8521 PROMPT_RELOCATE, 0 },
8523 /* Inode bitmap is on a bad block */
8524 { PR_1_IB_BAD_BLOCK,
8525 N_("@g %g's @i @B (%b) is bad. "),
8526 PROMPT_RELOCATE, 0 },
8528 /* Inode has incorrect i_size */
8529 { PR_1_BAD_I_SIZE,
8530 N_("@i %i, i_size is %Is, @s %N. "),
8531 PROMPT_FIX, PR_PREEN_OK },
8533 /* Inode has incorrect i_blocks */
8534 { PR_1_BAD_I_BLOCKS,
8535 N_("@i %i, i_@bs is %Ib, @s %N. "),
8536 PROMPT_FIX, PR_PREEN_OK },
8538 /* Illegal blocknumber in inode */
8539 { PR_1_ILLEGAL_BLOCK_NUM,
8540 N_("@I @b #%B (%b) in @i %i. "),
8541 PROMPT_CLEAR, PR_LATCH_BLOCK },
8543 /* Block number overlaps fs metadata */
8544 { PR_1_BLOCK_OVERLAPS_METADATA,
8545 N_("@b #%B (%b) overlaps @f metadata in @i %i. "),
8546 PROMPT_CLEAR, PR_LATCH_BLOCK },
8548 /* Inode has illegal blocks (latch question) */
8549 { PR_1_INODE_BLOCK_LATCH,
8550 N_("@i %i has illegal @b(s). "),
8551 PROMPT_CLEAR, 0 },
8553 /* Too many bad blocks in inode */
8554 { PR_1_TOO_MANY_BAD_BLOCKS,
8555 N_("Too many illegal @bs in @i %i.\n"),
8556 PROMPT_CLEAR_INODE, PR_NO_OK },
8558 /* Illegal block number in bad block inode */
8559 { PR_1_BB_ILLEGAL_BLOCK_NUM,
8560 N_("@I @b #%B (%b) in bad @b @i. "),
8561 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8563 /* Bad block inode has illegal blocks (latch question) */
8564 { PR_1_INODE_BBLOCK_LATCH,
8565 N_("Bad @b @i has illegal @b(s). "),
8566 PROMPT_CLEAR, 0 },
8568 /* Duplicate or bad blocks in use! */
8569 { PR_1_DUP_BLOCKS_PREENSTOP,
8570 N_("Duplicate or bad @b in use!\n"),
8571 PROMPT_NONE, 0 },
8573 /* Bad block used as bad block indirect block */
8574 { PR_1_BBINODE_BAD_METABLOCK,
8575 N_("Bad @b %b used as bad @b @i indirect @b. "),
8576 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8578 /* Inconsistency can't be fixed prompt */
8579 { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
8580 N_("\nThe bad @b @i has probably been corrupted. You probably\n"
8581 "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
8582 "in the @f.\n"),
8583 PROMPT_CONTINUE, PR_PREEN_NOMSG },
8585 /* Bad primary block */
8586 { PR_1_BAD_PRIMARY_BLOCK,
8587 N_("\nIf the @b is really bad, the @f cannot be fixed.\n"),
8588 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
8590 /* Bad primary block prompt */
8591 { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
8592 N_("You can remove this @b from the bad @b list and hope\n"
8593 "that the @b is really OK. But there are no guarantees.\n\n"),
8594 PROMPT_CLEAR, PR_PREEN_NOMSG },
8596 /* Bad primary superblock */
8597 { PR_1_BAD_PRIMARY_SUPERBLOCK,
8598 N_("The primary @S (%b) is on the bad @b list.\n"),
8599 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8601 /* Bad primary block group descriptors */
8602 { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
8603 N_("Block %b in the primary @g descriptors "
8604 "is on the bad @b list\n"),
8605 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8607 /* Bad superblock in group */
8608 { PR_1_BAD_SUPERBLOCK,
8609 N_("Warning: Group %g's @S (%b) is bad.\n"),
8610 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8612 /* Bad block group descriptors in group */
8613 { PR_1_BAD_GROUP_DESCRIPTORS,
8614 N_("Warning: Group %g's copy of the @g descriptors has a bad "
8615 "@b (%b).\n"),
8616 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8618 /* Block claimed for no reason */
8619 { PR_1_PROGERR_CLAIMED_BLOCK,
8620 N_("Programming error? @b #%b claimed for no reason in "
8621 "process_bad_@b.\n"),
8622 PROMPT_NONE, PR_PREEN_OK },
8624 /* Error allocating blocks for relocating metadata */
8625 { PR_1_RELOC_BLOCK_ALLOCATE,
8626 N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
8627 PROMPT_NONE, PR_PREEN_OK },
8629 /* Error allocating block buffer during relocation process */
8630 { PR_1_RELOC_MEMORY_ALLOCATE,
8631 N_("@A @b buffer for relocating %s\n"),
8632 PROMPT_NONE, PR_PREEN_OK },
8634 /* Relocating metadata group information from X to Y */
8635 { PR_1_RELOC_FROM_TO,
8636 N_("Relocating @g %g's %s from %b to %c...\n"),
8637 PROMPT_NONE, PR_PREEN_OK },
8639 /* Relocating metatdata group information to X */
8640 { PR_1_RELOC_TO,
8641 N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
8642 PROMPT_NONE, PR_PREEN_OK },
8644 /* Block read error during relocation process */
8645 { PR_1_RELOC_READ_ERR,
8646 N_("Warning: could not read @b %b of %s: %m\n"),
8647 PROMPT_NONE, PR_PREEN_OK },
8649 /* Block write error during relocation process */
8650 { PR_1_RELOC_WRITE_ERR,
8651 N_("Warning: could not write @b %b for %s: %m\n"),
8652 PROMPT_NONE, PR_PREEN_OK },
8654 /* Error allocating inode bitmap */
8655 { PR_1_ALLOCATE_IBITMAP_ERROR,
8656 N_("@A @i @B (%N): %m\n"),
8657 PROMPT_NONE, PR_FATAL },
8659 /* Error allocating block bitmap */
8660 { PR_1_ALLOCATE_BBITMAP_ERROR,
8661 N_("@A @b @B (%N): %m\n"),
8662 PROMPT_NONE, PR_FATAL },
8664 /* Error allocating icount structure */
8665 { PR_1_ALLOCATE_ICOUNT,
8666 N_("@A icount link information: %m\n"),
8667 PROMPT_NONE, PR_FATAL },
8669 /* Error allocating dbcount */
8670 { PR_1_ALLOCATE_DBCOUNT,
8671 N_("@A @d @b array: %m\n"),
8672 PROMPT_NONE, PR_FATAL },
8674 /* Error while scanning inodes */
8675 { PR_1_ISCAN_ERROR,
8676 N_("Error while scanning @is (%i): %m\n"),
8677 PROMPT_NONE, PR_FATAL },
8679 /* Error while iterating over blocks */
8680 { PR_1_BLOCK_ITERATE,
8681 N_("Error while iterating over @bs in @i %i: %m\n"),
8682 PROMPT_NONE, PR_FATAL },
8684 /* Error while storing inode count information */
8685 { PR_1_ICOUNT_STORE,
8686 N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
8687 PROMPT_NONE, PR_FATAL },
8689 /* Error while storing directory block information */
8690 { PR_1_ADD_DBLOCK,
8691 N_("Error storing @d @b information "
8692 "(@i=%i, @b=%b, num=%N): %m\n"),
8693 PROMPT_NONE, PR_FATAL },
8695 /* Error while reading inode (for clearing) */
8696 { PR_1_READ_INODE,
8697 N_("Error reading @i %i: %m\n"),
8698 PROMPT_NONE, PR_FATAL },
8700 /* Suppress messages prompt */
8701 { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
8703 /* Imagic flag set on an inode when filesystem doesn't support it */
8704 { PR_1_SET_IMAGIC,
8705 N_("@i %i has imagic flag set. "),
8706 PROMPT_CLEAR, 0 },
8708 /* Immutable flag set on a device or socket inode */
8709 { PR_1_SET_IMMUTABLE,
8710 N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
8711 "or append-only flag set. "),
8712 PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
8714 /* Compression flag set on an inode when filesystem doesn't support it */
8715 { PR_1_COMPR_SET,
8716 N_("@i %i has @cion flag set on @f without @cion support. "),
8717 PROMPT_CLEAR, 0 },
8719 /* Non-zero size for device, fifo or socket inode */
8720 { PR_1_SET_NONZSIZE,
8721 N_("Special (@v/socket/fifo) @i %i has non-zero size. "),
8722 PROMPT_FIX, PR_PREEN_OK },
8724 /* Filesystem revision is 0, but feature flags are set */
8725 { PR_1_FS_REV_LEVEL,
8726 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8727 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8729 /* Journal inode is not in use, but contains data */
8730 { PR_1_JOURNAL_INODE_NOT_CLEAR,
8731 N_("@j @i is not in use, but contains data. "),
8732 PROMPT_CLEAR, PR_PREEN_OK },
8734 /* Journal has bad mode */
8735 { PR_1_JOURNAL_BAD_MODE,
8736 N_("@j is not regular file. "),
8737 PROMPT_FIX, PR_PREEN_OK },
8739 /* Deal with inodes that were part of orphan linked list */
8740 { PR_1_LOW_DTIME,
8741 N_("@i %i was part of the @o @i list. "),
8742 PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
8744 /* Deal with inodes that were part of corrupted orphan linked
8745 list (latch question) */
8746 { PR_1_ORPHAN_LIST_REFUGEES,
8747 N_("@is that were part of a corrupted orphan linked list found. "),
8748 PROMPT_FIX, 0 },
8750 /* Error allocating refcount structure */
8751 { PR_1_ALLOCATE_REFCOUNT,
8752 N_("@A refcount structure (%N): %m\n"),
8753 PROMPT_NONE, PR_FATAL },
8755 /* Error reading extended attribute block */
8756 { PR_1_READ_EA_BLOCK,
8757 N_("Error reading @a @b %b for @i %i. "),
8758 PROMPT_CLEAR, 0 },
8760 /* Invalid extended attribute block */
8761 { PR_1_BAD_EA_BLOCK,
8762 N_("@i %i has a bad @a @b %b. "),
8763 PROMPT_CLEAR, 0 },
8765 /* Error reading Extended Attribute block while fixing refcount */
8766 { PR_1_EXTATTR_READ_ABORT,
8767 N_("Error reading @a @b %b (%m). "),
8768 PROMPT_ABORT, 0 },
8770 /* Extended attribute reference count incorrect */
8771 { PR_1_EXTATTR_REFCOUNT,
8772 N_("@a @b %b has reference count %B, @s %N. "),
8773 PROMPT_FIX, 0 },
8775 /* Error writing Extended Attribute block while fixing refcount */
8776 { PR_1_EXTATTR_WRITE,
8777 N_("Error writing @a @b %b (%m). "),
8778 PROMPT_ABORT, 0 },
8780 /* Multiple EA blocks not supported */
8781 { PR_1_EA_MULTI_BLOCK,
8782 N_("@a @b %b has h_@bs > 1. "),
8783 PROMPT_CLEAR, 0},
8785 /* Error allocating EA region allocation structure */
8786 { PR_1_EA_ALLOC_REGION,
8787 N_("@A @a @b %b. "),
8788 PROMPT_ABORT, 0},
8790 /* Error EA allocation collision */
8791 { PR_1_EA_ALLOC_COLLISION,
8792 N_("@a @b %b is corrupt (allocation collision). "),
8793 PROMPT_CLEAR, 0},
8795 /* Bad extended attribute name */
8796 { PR_1_EA_BAD_NAME,
8797 N_("@a @b %b is corrupt (@n name). "),
8798 PROMPT_CLEAR, 0},
8800 /* Bad extended attribute value */
8801 { PR_1_EA_BAD_VALUE,
8802 N_("@a @b %b is corrupt (@n value). "),
8803 PROMPT_CLEAR, 0},
8805 /* Inode too big (latch question) */
8806 { PR_1_INODE_TOOBIG,
8807 N_("@i %i is too big. "), PROMPT_TRUNCATE, 0 },
8809 /* Directory too big */
8810 { PR_1_TOOBIG_DIR,
8811 N_("@b #%B (%b) causes @d to be too big. "),
8812 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8814 /* Regular file too big */
8815 { PR_1_TOOBIG_REG,
8816 N_("@b #%B (%b) causes file to be too big. "),
8817 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8819 /* Symlink too big */
8820 { PR_1_TOOBIG_SYMLINK,
8821 N_("@b #%B (%b) causes symlink to be too big. "),
8822 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8824 /* INDEX_FL flag set on a non-HTREE filesystem */
8825 { PR_1_HTREE_SET,
8826 N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
8827 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8829 /* INDEX_FL flag set on a non-directory */
8830 { PR_1_HTREE_NODIR,
8831 N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
8832 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8834 /* Invalid root node in HTREE directory */
8835 { PR_1_HTREE_BADROOT,
8836 N_("@h %i has an @n root node.\n"),
8837 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8839 /* Unsupported hash version in HTREE directory */
8840 { PR_1_HTREE_HASHV,
8841 N_("@h %i has an unsupported hash version (%N)\n"),
8842 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8844 /* Incompatible flag in HTREE root node */
8845 { PR_1_HTREE_INCOMPAT,
8846 N_("@h %i uses an incompatible htree root node flag.\n"),
8847 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8849 /* HTREE too deep */
8850 { PR_1_HTREE_DEPTH,
8851 N_("@h %i has a tree depth (%N) which is too big\n"),
8852 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8854 /* Bad block has indirect block that conflicts with filesystem block */
8855 { PR_1_BB_FS_BLOCK,
8856 N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
8857 "@f metadata. "),
8858 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8860 /* Resize inode failed */
8861 { PR_1_RESIZE_INODE_CREATE,
8862 N_("Resize @i (re)creation failed: %m."),
8863 PROMPT_ABORT, 0 },
8865 /* invalid inode->i_extra_isize */
8866 { PR_1_EXTRA_ISIZE,
8867 N_("@i %i has a extra size (%IS) which is @n\n"),
8868 PROMPT_FIX, PR_PREEN_OK },
8870 /* invalid ea entry->e_name_len */
8871 { PR_1_ATTR_NAME_LEN,
8872 N_("@a in @i %i has a namelen (%N) which is @n\n"),
8873 PROMPT_CLEAR, PR_PREEN_OK },
8875 /* invalid ea entry->e_value_size */
8876 { PR_1_ATTR_VALUE_SIZE,
8877 N_("@a in @i %i has a value size (%N) which is @n\n"),
8878 PROMPT_CLEAR, PR_PREEN_OK },
8880 /* invalid ea entry->e_value_offs */
8881 { PR_1_ATTR_VALUE_OFFSET,
8882 N_("@a in @i %i has a value offset (%N) which is @n\n"),
8883 PROMPT_CLEAR, PR_PREEN_OK },
8885 /* invalid ea entry->e_value_block */
8886 { PR_1_ATTR_VALUE_BLOCK,
8887 N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
8888 PROMPT_CLEAR, PR_PREEN_OK },
8890 /* invalid ea entry->e_hash */
8891 { PR_1_ATTR_HASH,
8892 N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
8893 PROMPT_CLEAR, PR_PREEN_OK },
8895 /* Pass 1b errors */
8897 /* Pass 1B: Rescan for duplicate/bad blocks */
8898 { PR_1B_PASS_HEADER,
8899 N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
8900 "Pass 1B: Rescanning for @m @bs\n"),
8901 PROMPT_NONE, 0 },
8903 /* Duplicate/bad block(s) header */
8904 { PR_1B_DUP_BLOCK_HEADER,
8905 N_("@m @b(s) in @i %i:"),
8906 PROMPT_NONE, 0 },
8908 /* Duplicate/bad block(s) in inode */
8909 { PR_1B_DUP_BLOCK,
8910 " %b",
8911 PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
8913 /* Duplicate/bad block(s) end */
8914 { PR_1B_DUP_BLOCK_END,
8915 "\n",
8916 PROMPT_NONE, PR_PREEN_NOHDR },
8918 /* Error while scanning inodes */
8919 { PR_1B_ISCAN_ERROR,
8920 N_("Error while scanning inodes (%i): %m\n"),
8921 PROMPT_NONE, PR_FATAL },
8923 /* Error allocating inode bitmap */
8924 { PR_1B_ALLOCATE_IBITMAP_ERROR,
8925 N_("@A @i @B (@i_dup_map): %m\n"),
8926 PROMPT_NONE, PR_FATAL },
8928 /* Error while iterating over blocks */
8929 { PR_1B_BLOCK_ITERATE,
8930 N_("Error while iterating over @bs in @i %i (%s): %m\n"),
8931 PROMPT_NONE, 0 },
8933 /* Error adjusting EA refcount */
8934 { PR_1B_ADJ_EA_REFCOUNT,
8935 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
8936 PROMPT_NONE, 0 },
8939 /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
8940 { PR_1C_PASS_HEADER,
8941 N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
8942 PROMPT_NONE, 0 },
8945 /* Pass 1D: Reconciling multiply-claimed blocks */
8946 { PR_1D_PASS_HEADER,
8947 N_("Pass 1D: Reconciling @m @bs\n"),
8948 PROMPT_NONE, 0 },
8950 /* File has duplicate blocks */
8951 { PR_1D_DUP_FILE,
8952 N_("File %Q (@i #%i, mod time %IM)\n"
8953 " has %B @m @b(s), shared with %N file(s):\n"),
8954 PROMPT_NONE, 0 },
8956 /* List of files sharing duplicate blocks */
8957 { PR_1D_DUP_FILE_LIST,
8958 N_("\t%Q (@i #%i, mod time %IM)\n"),
8959 PROMPT_NONE, 0 },
8961 /* File sharing blocks with filesystem metadata */
8962 { PR_1D_SHARE_METADATA,
8963 N_("\t<@f metadata>\n"),
8964 PROMPT_NONE, 0 },
8966 /* Report of how many duplicate/bad inodes */
8967 { PR_1D_NUM_DUP_INODES,
8968 N_("(There are %N @is containing @m @bs.)\n\n"),
8969 PROMPT_NONE, 0 },
8971 /* Duplicated blocks already reassigned or cloned. */
8972 { PR_1D_DUP_BLOCKS_DEALT,
8973 N_("@m @bs already reassigned or cloned.\n\n"),
8974 PROMPT_NONE, 0 },
8976 /* Clone duplicate/bad blocks? */
8977 { PR_1D_CLONE_QUESTION,
8978 "", PROMPT_CLONE, PR_NO_OK },
8980 /* Delete file? */
8981 { PR_1D_DELETE_QUESTION,
8982 "", PROMPT_DELETE, 0 },
8984 /* Couldn't clone file (error) */
8985 { PR_1D_CLONE_ERROR,
8986 N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
8988 /* Pass 2 errors */
8990 /* Pass 2: Checking directory structure */
8991 { PR_2_PASS_HEADER,
8992 N_("Pass 2: Checking @d structure\n"),
8993 PROMPT_NONE, 0 },
8995 /* Bad inode number for '.' */
8996 { PR_2_BAD_INODE_DOT,
8997 N_("@n @i number for '.' in @d @i %i.\n"),
8998 PROMPT_FIX, 0 },
9000 /* Directory entry has bad inode number */
9001 { PR_2_BAD_INO,
9002 N_("@E has @n @i #: %Di.\n"),
9003 PROMPT_CLEAR, 0 },
9005 /* Directory entry has deleted or unused inode */
9006 { PR_2_UNUSED_INODE,
9007 N_("@E has @D/unused @i %Di. "),
9008 PROMPT_CLEAR, PR_PREEN_OK },
9010 /* Directry entry is link to '.' */
9011 { PR_2_LINK_DOT,
9012 N_("@E @L to '.' "),
9013 PROMPT_CLEAR, 0 },
9015 /* Directory entry points to inode now located in a bad block */
9016 { PR_2_BB_INODE,
9017 N_("@E points to @i (%Di) located in a bad @b.\n"),
9018 PROMPT_CLEAR, 0 },
9020 /* Directory entry contains a link to a directory */
9021 { PR_2_LINK_DIR,
9022 N_("@E @L to @d %P (%Di).\n"),
9023 PROMPT_CLEAR, 0 },
9025 /* Directory entry contains a link to the root directry */
9026 { PR_2_LINK_ROOT,
9027 N_("@E @L to the @r.\n"),
9028 PROMPT_CLEAR, 0 },
9030 /* Directory entry has illegal characters in its name */
9031 { PR_2_BAD_NAME,
9032 N_("@E has illegal characters in its name.\n"),
9033 PROMPT_FIX, 0 },
9035 /* Missing '.' in directory inode */
9036 { PR_2_MISSING_DOT,
9037 N_("Missing '.' in @d @i %i.\n"),
9038 PROMPT_FIX, 0 },
9040 /* Missing '..' in directory inode */
9041 { PR_2_MISSING_DOT_DOT,
9042 N_("Missing '..' in @d @i %i.\n"),
9043 PROMPT_FIX, 0 },
9045 /* First entry in directory inode doesn't contain '.' */
9046 { PR_2_1ST_NOT_DOT,
9047 N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
9048 PROMPT_FIX, 0 },
9050 /* Second entry in directory inode doesn't contain '..' */
9051 { PR_2_2ND_NOT_DOT_DOT,
9052 N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
9053 PROMPT_FIX, 0 },
9055 /* i_faddr should be zero */
9056 { PR_2_FADDR_ZERO,
9057 N_("i_faddr @F %IF, @s zero.\n"),
9058 PROMPT_CLEAR, 0 },
9060 /* i_file_acl should be zero */
9061 { PR_2_FILE_ACL_ZERO,
9062 N_("i_file_acl @F %If, @s zero.\n"),
9063 PROMPT_CLEAR, 0 },
9065 /* i_dir_acl should be zero */
9066 { PR_2_DIR_ACL_ZERO,
9067 N_("i_dir_acl @F %Id, @s zero.\n"),
9068 PROMPT_CLEAR, 0 },
9070 /* i_frag should be zero */
9071 { PR_2_FRAG_ZERO,
9072 N_("i_frag @F %N, @s zero.\n"),
9073 PROMPT_CLEAR, 0 },
9075 /* i_fsize should be zero */
9076 { PR_2_FSIZE_ZERO,
9077 N_("i_fsize @F %N, @s zero.\n"),
9078 PROMPT_CLEAR, 0 },
9080 /* inode has bad mode */
9081 { PR_2_BAD_MODE,
9082 N_("@i %i (%Q) has @n mode (%Im).\n"),
9083 PROMPT_CLEAR, 0 },
9085 /* directory corrupted */
9086 { PR_2_DIR_CORRUPTED,
9087 N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
9088 PROMPT_SALVAGE, 0 },
9090 /* filename too long */
9091 { PR_2_FILENAME_LONG,
9092 N_("@d @i %i, @b %B, offset %N: filename too long\n"),
9093 PROMPT_TRUNCATE, 0 },
9095 /* Directory inode has a missing block (hole) */
9096 { PR_2_DIRECTORY_HOLE,
9097 N_("@d @i %i has an unallocated @b #%B. "),
9098 PROMPT_ALLOCATE, 0 },
9100 /* '.' is not NULL terminated */
9101 { PR_2_DOT_NULL_TERM,
9102 N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
9103 PROMPT_FIX, 0 },
9105 /* '..' is not NULL terminated */
9106 { PR_2_DOT_DOT_NULL_TERM,
9107 N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
9108 PROMPT_FIX, 0 },
9110 /* Illegal character device inode */
9111 { PR_2_BAD_CHAR_DEV,
9112 N_("@i %i (%Q) is an @I character @v.\n"),
9113 PROMPT_CLEAR, 0 },
9115 /* Illegal block device inode */
9116 { PR_2_BAD_BLOCK_DEV,
9117 N_("@i %i (%Q) is an @I @b @v.\n"),
9118 PROMPT_CLEAR, 0 },
9120 /* Duplicate '.' entry */
9121 { PR_2_DUP_DOT,
9122 N_("@E is duplicate '.' @e.\n"),
9123 PROMPT_FIX, 0 },
9125 /* Duplicate '..' entry */
9126 { PR_2_DUP_DOT_DOT,
9127 N_("@E is duplicate '..' @e.\n"),
9128 PROMPT_FIX, 0 },
9130 /* Internal error: couldn't find dir_info */
9131 { PR_2_NO_DIRINFO,
9132 N_("Internal error: cannot find dir_info for %i.\n"),
9133 PROMPT_NONE, PR_FATAL },
9135 /* Final rec_len is wrong */
9136 { PR_2_FINAL_RECLEN,
9137 N_("@E has rec_len of %Dr, @s %N.\n"),
9138 PROMPT_FIX, 0 },
9140 /* Error allocating icount structure */
9141 { PR_2_ALLOCATE_ICOUNT,
9142 N_("@A icount structure: %m\n"),
9143 PROMPT_NONE, PR_FATAL },
9145 /* Error iterating over directory blocks */
9146 { PR_2_DBLIST_ITERATE,
9147 N_("Error iterating over @d @bs: %m\n"),
9148 PROMPT_NONE, PR_FATAL },
9150 /* Error reading directory block */
9151 { PR_2_READ_DIRBLOCK,
9152 N_("Error reading @d @b %b (@i %i): %m\n"),
9153 PROMPT_CONTINUE, 0 },
9155 /* Error writing directory block */
9156 { PR_2_WRITE_DIRBLOCK,
9157 N_("Error writing @d @b %b (@i %i): %m\n"),
9158 PROMPT_CONTINUE, 0 },
9160 /* Error allocating new directory block */
9161 { PR_2_ALLOC_DIRBOCK,
9162 N_("@A new @d @b for @i %i (%s): %m\n"),
9163 PROMPT_NONE, 0 },
9165 /* Error deallocating inode */
9166 { PR_2_DEALLOC_INODE,
9167 N_("Error deallocating @i %i: %m\n"),
9168 PROMPT_NONE, PR_FATAL },
9170 /* Directory entry for '.' is big. Split? */
9171 { PR_2_SPLIT_DOT,
9172 N_("@d @e for '.' is big. "),
9173 PROMPT_SPLIT, PR_NO_OK },
9175 /* Illegal FIFO inode */
9176 { PR_2_BAD_FIFO,
9177 N_("@i %i (%Q) is an @I FIFO.\n"),
9178 PROMPT_CLEAR, 0 },
9180 /* Illegal socket inode */
9181 { PR_2_BAD_SOCKET,
9182 N_("@i %i (%Q) is an @I socket.\n"),
9183 PROMPT_CLEAR, 0 },
9185 /* Directory filetype not set */
9186 { PR_2_SET_FILETYPE,
9187 N_("Setting filetype for @E to %N.\n"),
9188 PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
9190 /* Directory filetype incorrect */
9191 { PR_2_BAD_FILETYPE,
9192 N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
9193 PROMPT_FIX, 0 },
9195 /* Directory filetype set on filesystem */
9196 { PR_2_CLEAR_FILETYPE,
9197 N_("@E has filetype set.\n"),
9198 PROMPT_CLEAR, PR_PREEN_OK },
9200 /* Directory filename is null */
9201 { PR_2_NULL_NAME,
9202 N_("@E has a @z name.\n"),
9203 PROMPT_CLEAR, 0 },
9205 /* Invalid symlink */
9206 { PR_2_INVALID_SYMLINK,
9207 N_("Symlink %Q (@i #%i) is @n.\n"),
9208 PROMPT_CLEAR, 0 },
9210 /* i_file_acl (extended attribute block) is bad */
9211 { PR_2_FILE_ACL_BAD,
9212 N_("@a @b @F @n (%If).\n"),
9213 PROMPT_CLEAR, 0 },
9215 /* Filesystem contains large files, but has no such flag in sb */
9216 { PR_2_FEATURE_LARGE_FILES,
9217 N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
9218 PROMPT_FIX, 0 },
9220 /* Node in HTREE directory not referenced */
9221 { PR_2_HTREE_NOTREF,
9222 N_("@p @h %d: node (%B) not referenced\n"),
9223 PROMPT_NONE, 0 },
9225 /* Node in HTREE directory referenced twice */
9226 { PR_2_HTREE_DUPREF,
9227 N_("@p @h %d: node (%B) referenced twice\n"),
9228 PROMPT_NONE, 0 },
9230 /* Node in HTREE directory has bad min hash */
9231 { PR_2_HTREE_MIN_HASH,
9232 N_("@p @h %d: node (%B) has bad min hash\n"),
9233 PROMPT_NONE, 0 },
9235 /* Node in HTREE directory has bad max hash */
9236 { PR_2_HTREE_MAX_HASH,
9237 N_("@p @h %d: node (%B) has bad max hash\n"),
9238 PROMPT_NONE, 0 },
9240 /* Clear invalid HTREE directory */
9241 { PR_2_HTREE_CLEAR,
9242 N_("@n @h %d (%q). "), PROMPT_CLEAR, 0 },
9244 /* Bad block in htree interior node */
9245 { PR_2_HTREE_BADBLK,
9246 N_("@p @h %d (%q): bad @b number %b.\n"),
9247 PROMPT_CLEAR_HTREE, 0 },
9249 /* Error adjusting EA refcount */
9250 { PR_2_ADJ_EA_REFCOUNT,
9251 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
9252 PROMPT_NONE, PR_FATAL },
9254 /* Invalid HTREE root node */
9255 { PR_2_HTREE_BAD_ROOT,
9256 N_("@p @h %d: root node is @n\n"),
9257 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9259 /* Invalid HTREE limit */
9260 { PR_2_HTREE_BAD_LIMIT,
9261 N_("@p @h %d: node (%B) has @n limit (%N)\n"),
9262 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9264 /* Invalid HTREE count */
9265 { PR_2_HTREE_BAD_COUNT,
9266 N_("@p @h %d: node (%B) has @n count (%N)\n"),
9267 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9269 /* HTREE interior node has out-of-order hashes in table */
9270 { PR_2_HTREE_HASH_ORDER,
9271 N_("@p @h %d: node (%B) has an unordered hash table\n"),
9272 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9274 /* Node in HTREE directory has invalid depth */
9275 { PR_2_HTREE_BAD_DEPTH,
9276 N_("@p @h %d: node (%B) has @n depth\n"),
9277 PROMPT_NONE, 0 },
9279 /* Duplicate directory entry found */
9280 { PR_2_DUPLICATE_DIRENT,
9281 N_("Duplicate @E found. "),
9282 PROMPT_CLEAR, 0 },
9284 /* Non-unique filename found */
9285 { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
9286 N_("@E has a non-unique filename.\nRename to %s"),
9287 PROMPT_NULL, 0 },
9289 /* Duplicate directory entry found */
9290 { PR_2_REPORT_DUP_DIRENT,
9291 N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
9292 PROMPT_NONE, 0 },
9294 /* Pass 3 errors */
9296 /* Pass 3: Checking directory connectivity */
9297 { PR_3_PASS_HEADER,
9298 N_("Pass 3: Checking @d connectivity\n"),
9299 PROMPT_NONE, 0 },
9301 /* Root inode not allocated */
9302 { PR_3_NO_ROOT_INODE,
9303 N_("@r not allocated. "),
9304 PROMPT_ALLOCATE, 0 },
9306 /* No room in lost+found */
9307 { PR_3_EXPAND_LF_DIR,
9308 N_("No room in @l @d. "),
9309 PROMPT_EXPAND, 0 },
9311 /* Unconnected directory inode */
9312 { PR_3_UNCONNECTED_DIR,
9313 N_("Unconnected @d @i %i (%p)\n"),
9314 PROMPT_CONNECT, 0 },
9316 /* /lost+found not found */
9317 { PR_3_NO_LF_DIR,
9318 N_("/@l not found. "),
9319 PROMPT_CREATE, PR_PREEN_OK },
9321 /* .. entry is incorrect */
9322 { PR_3_BAD_DOT_DOT,
9323 N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
9324 PROMPT_FIX, 0 },
9326 /* Bad or non-existent /lost+found. Cannot reconnect */
9327 { PR_3_NO_LPF,
9328 N_("Bad or non-existent /@l. Cannot reconnect.\n"),
9329 PROMPT_NONE, 0 },
9331 /* Could not expand /lost+found */
9332 { PR_3_CANT_EXPAND_LPF,
9333 N_("Could not expand /@l: %m\n"),
9334 PROMPT_NONE, 0 },
9336 /* Could not reconnect inode */
9337 { PR_3_CANT_RECONNECT,
9338 N_("Could not reconnect %i: %m\n"),
9339 PROMPT_NONE, 0 },
9341 /* Error while trying to find /lost+found */
9342 { PR_3_ERR_FIND_LPF,
9343 N_("Error while trying to find /@l: %m\n"),
9344 PROMPT_NONE, 0 },
9346 /* Error in ext2fs_new_block while creating /lost+found */
9347 { PR_3_ERR_LPF_NEW_BLOCK,
9348 N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
9349 PROMPT_NONE, 0 },
9351 /* Error in ext2fs_new_inode while creating /lost+found */
9352 { PR_3_ERR_LPF_NEW_INODE,
9353 N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
9354 PROMPT_NONE, 0 },
9356 /* Error in ext2fs_new_dir_block while creating /lost+found */
9357 { PR_3_ERR_LPF_NEW_DIR_BLOCK,
9358 N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
9359 PROMPT_NONE, 0 },
9361 /* Error while writing directory block for /lost+found */
9362 { PR_3_ERR_LPF_WRITE_BLOCK,
9363 N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
9364 PROMPT_NONE, 0 },
9366 /* Error while adjusting inode count */
9367 { PR_3_ADJUST_INODE,
9368 N_("Error while adjusting @i count on @i %i\n"),
9369 PROMPT_NONE, 0 },
9371 /* Couldn't fix parent directory -- error */
9372 { PR_3_FIX_PARENT_ERR,
9373 N_("Couldn't fix parent of @i %i: %m\n\n"),
9374 PROMPT_NONE, 0 },
9376 /* Couldn't fix parent directory -- couldn't find it */
9377 { PR_3_FIX_PARENT_NOFIND,
9378 N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
9379 PROMPT_NONE, 0 },
9381 /* Error allocating inode bitmap */
9382 { PR_3_ALLOCATE_IBITMAP_ERROR,
9383 N_("@A @i @B (%N): %m\n"),
9384 PROMPT_NONE, PR_FATAL },
9386 /* Error creating root directory */
9387 { PR_3_CREATE_ROOT_ERROR,
9388 N_("Error creating root @d (%s): %m\n"),
9389 PROMPT_NONE, PR_FATAL },
9391 /* Error creating lost and found directory */
9392 { PR_3_CREATE_LPF_ERROR,
9393 N_("Error creating /@l @d (%s): %m\n"),
9394 PROMPT_NONE, PR_FATAL },
9396 /* Root inode is not directory; aborting */
9397 { PR_3_ROOT_NOT_DIR_ABORT,
9398 N_("@r is not a @d; aborting.\n"),
9399 PROMPT_NONE, PR_FATAL },
9401 /* Cannot proceed without a root inode. */
9402 { PR_3_NO_ROOT_INODE_ABORT,
9403 N_("can't proceed without a @r.\n"),
9404 PROMPT_NONE, PR_FATAL },
9406 /* Internal error: couldn't find dir_info */
9407 { PR_3_NO_DIRINFO,
9408 N_("Internal error: cannot find dir_info for %i.\n"),
9409 PROMPT_NONE, PR_FATAL },
9411 /* Lost+found not a directory */
9412 { PR_3_LPF_NOTDIR,
9413 N_("/@l is not a @d (ino=%i)\n"),
9414 PROMPT_UNLINK, 0 },
9416 /* Pass 3A Directory Optimization */
9418 /* Pass 3A: Optimizing directories */
9419 { PR_3A_PASS_HEADER,
9420 N_("Pass 3A: Optimizing directories\n"),
9421 PROMPT_NONE, PR_PREEN_NOMSG },
9423 /* Error iterating over directories */
9424 { PR_3A_OPTIMIZE_ITER,
9425 N_("Failed to create dirs_to_hash iterator: %m"),
9426 PROMPT_NONE, 0 },
9428 /* Error rehash directory */
9429 { PR_3A_OPTIMIZE_DIR_ERR,
9430 N_("Failed to optimize directory %q (%d): %m"),
9431 PROMPT_NONE, 0 },
9433 /* Rehashing dir header */
9434 { PR_3A_OPTIMIZE_DIR_HEADER,
9435 N_("Optimizing directories: "),
9436 PROMPT_NONE, PR_MSG_ONLY },
9438 /* Rehashing directory %d */
9439 { PR_3A_OPTIMIZE_DIR,
9440 " %d",
9441 PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
9443 /* Rehashing dir end */
9444 { PR_3A_OPTIMIZE_DIR_END,
9445 "\n",
9446 PROMPT_NONE, PR_PREEN_NOHDR },
9448 /* Pass 4 errors */
9450 /* Pass 4: Checking reference counts */
9451 { PR_4_PASS_HEADER,
9452 N_("Pass 4: Checking reference counts\n"),
9453 PROMPT_NONE, 0 },
9455 /* Unattached zero-length inode */
9456 { PR_4_ZERO_LEN_INODE,
9457 N_("@u @z @i %i. "),
9458 PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
9460 /* Unattached inode */
9461 { PR_4_UNATTACHED_INODE,
9462 N_("@u @i %i\n"),
9463 PROMPT_CONNECT, 0 },
9465 /* Inode ref count wrong */
9466 { PR_4_BAD_REF_COUNT,
9467 N_("@i %i ref count is %Il, @s %N. "),
9468 PROMPT_FIX, PR_PREEN_OK },
9470 { PR_4_INCONSISTENT_COUNT,
9471 N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
9472 "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
9473 "@i_link_info[%i] is %N, @i.i_links_count is %Il. "
9474 "They @s the same!\n"),
9475 PROMPT_NONE, 0 },
9477 /* Pass 5 errors */
9479 /* Pass 5: Checking group summary information */
9480 { PR_5_PASS_HEADER,
9481 N_("Pass 5: Checking @g summary information\n"),
9482 PROMPT_NONE, 0 },
9484 /* Padding at end of inode bitmap is not set. */
9485 { PR_5_INODE_BMAP_PADDING,
9486 N_("Padding at end of @i @B is not set. "),
9487 PROMPT_FIX, PR_PREEN_OK },
9489 /* Padding at end of block bitmap is not set. */
9490 { PR_5_BLOCK_BMAP_PADDING,
9491 N_("Padding at end of @b @B is not set. "),
9492 PROMPT_FIX, PR_PREEN_OK },
9494 /* Block bitmap differences header */
9495 { PR_5_BLOCK_BITMAP_HEADER,
9496 N_("@b @B differences: "),
9497 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
9499 /* Block not used, but marked in bitmap */
9500 { PR_5_BLOCK_UNUSED,
9501 " -%b",
9502 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9504 /* Block used, but not marked used in bitmap */
9505 { PR_5_BLOCK_USED,
9506 " +%b",
9507 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9509 /* Block bitmap differences end */
9510 { PR_5_BLOCK_BITMAP_END,
9511 "\n",
9512 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9514 /* Inode bitmap differences header */
9515 { PR_5_INODE_BITMAP_HEADER,
9516 N_("@i @B differences: "),
9517 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9519 /* Inode not used, but marked in bitmap */
9520 { PR_5_INODE_UNUSED,
9521 " -%i",
9522 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9524 /* Inode used, but not marked used in bitmap */
9525 { PR_5_INODE_USED,
9526 " +%i",
9527 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9529 /* Inode bitmap differences end */
9530 { PR_5_INODE_BITMAP_END,
9531 "\n",
9532 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9534 /* Free inodes count for group wrong */
9535 { PR_5_FREE_INODE_COUNT_GROUP,
9536 N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
9537 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9539 /* Directories count for group wrong */
9540 { PR_5_FREE_DIR_COUNT_GROUP,
9541 N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
9542 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9544 /* Free inodes count wrong */
9545 { PR_5_FREE_INODE_COUNT,
9546 N_("Free @is count wrong (%i, counted=%j).\n"),
9547 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9549 /* Free blocks count for group wrong */
9550 { PR_5_FREE_BLOCK_COUNT_GROUP,
9551 N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
9552 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9554 /* Free blocks count wrong */
9555 { PR_5_FREE_BLOCK_COUNT,
9556 N_("Free @bs count wrong (%b, counted=%c).\n"),
9557 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9559 /* Programming error: bitmap endpoints don't match */
9560 { PR_5_BMAP_ENDPOINTS,
9561 N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
9562 "match calculated @B endpoints (%i, %j)\n"),
9563 PROMPT_NONE, PR_FATAL },
9565 /* Internal error: fudging end of bitmap */
9566 { PR_5_FUDGE_BITMAP_ERROR,
9567 N_("Internal error: fudging end of bitmap (%N)\n"),
9568 PROMPT_NONE, PR_FATAL },
9570 /* Error copying in replacement inode bitmap */
9571 { PR_5_COPY_IBITMAP_ERROR,
9572 N_("Error copying in replacement @i @B: %m\n"),
9573 PROMPT_NONE, PR_FATAL },
9575 /* Error copying in replacement block bitmap */
9576 { PR_5_COPY_BBITMAP_ERROR,
9577 N_("Error copying in replacement @b @B: %m\n"),
9578 PROMPT_NONE, PR_FATAL },
9580 /* Block range not used, but marked in bitmap */
9581 { PR_5_BLOCK_RANGE_UNUSED,
9582 " -(%b--%c)",
9583 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9585 /* Block range used, but not marked used in bitmap */
9586 { PR_5_BLOCK_RANGE_USED,
9587 " +(%b--%c)",
9588 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9590 /* Inode range not used, but marked in bitmap */
9591 { PR_5_INODE_RANGE_UNUSED,
9592 " -(%i--%j)",
9593 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9595 /* Inode range used, but not marked used in bitmap */
9596 { PR_5_INODE_RANGE_USED,
9597 " +(%i--%j)",
9598 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9600 { 0 }
9604 * This is the latch flags register. It allows several problems to be
9605 * "latched" together. This means that the user has to answer but one
9606 * question for the set of problems, and all of the associated
9607 * problems will be either fixed or not fixed.
9609 static struct latch_descr pr_latch_info[] = {
9610 { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
9611 { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
9612 { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
9613 { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
9614 { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
9615 { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
9616 { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
9617 { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
9618 { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
9619 { -1, 0, 0 },
9622 static const struct e2fsck_problem *find_problem(problem_t code)
9624 int i;
9626 for (i=0; problem_table[i].e2p_code; i++) {
9627 if (problem_table[i].e2p_code == code)
9628 return &problem_table[i];
9630 return 0;
9633 static struct latch_descr *find_latch(int code)
9635 int i;
9637 for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
9638 if (pr_latch_info[i].latch_code == code)
9639 return &pr_latch_info[i];
9641 return 0;
9644 int end_problem_latch(e2fsck_t ctx, int mask)
9646 struct latch_descr *ldesc;
9647 struct problem_context pctx;
9648 int answer = -1;
9650 ldesc = find_latch(mask);
9651 if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
9652 clear_problem_context(&pctx);
9653 answer = fix_problem(ctx, ldesc->end_message, &pctx);
9655 ldesc->flags &= ~(PRL_VARIABLE);
9656 return answer;
9659 int set_latch_flags(int mask, int setflags, int clearflags)
9661 struct latch_descr *ldesc;
9663 ldesc = find_latch(mask);
9664 if (!ldesc)
9665 return -1;
9666 ldesc->flags |= setflags;
9667 ldesc->flags &= ~clearflags;
9668 return 0;
9671 void clear_problem_context(struct problem_context *ctx)
9673 memset(ctx, 0, sizeof(struct problem_context));
9674 ctx->blkcount = -1;
9675 ctx->group = -1;
9678 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
9680 ext2_filsys fs = ctx->fs;
9681 const struct e2fsck_problem *ptr;
9682 struct latch_descr *ldesc = NULL;
9683 const char *message;
9684 int def_yn, answer, ans;
9685 int print_answer = 0;
9686 int suppress = 0;
9688 ptr = find_problem(code);
9689 if (!ptr) {
9690 printf(_("Unhandled error code (0x%x)!\n"), code);
9691 return 0;
9693 def_yn = 1;
9694 if ((ptr->flags & PR_NO_DEFAULT) ||
9695 ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
9696 (ctx->options & E2F_OPT_NO))
9697 def_yn= 0;
9700 * Do special latch processing. This is where we ask the
9701 * latch question, if it exists
9703 if (ptr->flags & PR_LATCH_MASK) {
9704 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
9705 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
9706 ans = fix_problem(ctx, ldesc->question, pctx);
9707 if (ans == 1)
9708 ldesc->flags |= PRL_YES;
9709 if (ans == 0)
9710 ldesc->flags |= PRL_NO;
9711 ldesc->flags |= PRL_LATCHED;
9713 if (ldesc->flags & PRL_SUPPRESS)
9714 suppress++;
9716 if ((ptr->flags & PR_PREEN_NOMSG) &&
9717 (ctx->options & E2F_OPT_PREEN))
9718 suppress++;
9719 if ((ptr->flags & PR_NO_NOMSG) &&
9720 (ctx->options & E2F_OPT_NO))
9721 suppress++;
9722 if (!suppress) {
9723 message = ptr->e2p_description;
9724 if ((ctx->options & E2F_OPT_PREEN) &&
9725 !(ptr->flags & PR_PREEN_NOHDR)) {
9726 printf("%s: ", ctx->device_name ?
9727 ctx->device_name : ctx->filesystem_name);
9729 if (*message)
9730 print_e2fsck_message(ctx, _(message), pctx, 1);
9732 if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
9733 preenhalt(ctx);
9735 if (ptr->flags & PR_FATAL)
9736 bb_error_msg_and_die(0);
9738 if (ptr->prompt == PROMPT_NONE) {
9739 if (ptr->flags & PR_NOCOLLATE)
9740 answer = -1;
9741 else
9742 answer = def_yn;
9743 } else {
9744 if (ctx->options & E2F_OPT_PREEN) {
9745 answer = def_yn;
9746 if (!(ptr->flags & PR_PREEN_NOMSG))
9747 print_answer = 1;
9748 } else if ((ptr->flags & PR_LATCH_MASK) &&
9749 (ldesc->flags & (PRL_YES | PRL_NO))) {
9750 if (!suppress)
9751 print_answer = 1;
9752 if (ldesc->flags & PRL_YES)
9753 answer = 1;
9754 else
9755 answer = 0;
9756 } else
9757 answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
9758 if (!answer && !(ptr->flags & PR_NO_OK))
9759 ext2fs_unmark_valid(fs);
9761 if (print_answer)
9762 printf("%s.\n", answer ?
9763 _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
9766 if ((ptr->prompt == PROMPT_ABORT) && answer)
9767 bb_error_msg_and_die(0);
9769 if (ptr->flags & PR_AFTER_CODE)
9770 answer = fix_problem(ctx, ptr->second_code, pctx);
9772 return answer;
9776 * linux/fs/recovery.c
9778 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
9782 * Maintain information about the progress of the recovery job, so that
9783 * the different passes can carry information between them.
9785 struct recovery_info
9787 tid_t start_transaction;
9788 tid_t end_transaction;
9790 int nr_replays;
9791 int nr_revokes;
9792 int nr_revoke_hits;
9795 enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
9796 static int do_one_pass(journal_t *journal,
9797 struct recovery_info *info, enum passtype pass);
9798 static int scan_revoke_records(journal_t *, struct buffer_head *,
9799 tid_t, struct recovery_info *);
9802 * Read a block from the journal
9805 static int jread(struct buffer_head **bhp, journal_t *journal,
9806 unsigned int offset)
9808 int err;
9809 unsigned long blocknr;
9810 struct buffer_head *bh;
9812 *bhp = NULL;
9814 err = journal_bmap(journal, offset, &blocknr);
9816 if (err) {
9817 printf("JBD: bad block at offset %u\n", offset);
9818 return err;
9821 bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
9822 if (!bh)
9823 return -ENOMEM;
9825 if (!buffer_uptodate(bh)) {
9826 /* If this is a brand new buffer, start readahead.
9827 Otherwise, we assume we are already reading it. */
9828 if (!buffer_req(bh))
9829 do_readahead(journal, offset);
9830 wait_on_buffer(bh);
9833 if (!buffer_uptodate(bh)) {
9834 printf("JBD: Failed to read block at offset %u\n", offset);
9835 brelse(bh);
9836 return -EIO;
9839 *bhp = bh;
9840 return 0;
9845 * Count the number of in-use tags in a journal descriptor block.
9848 static int count_tags(struct buffer_head *bh, int size)
9850 char * tagp;
9851 journal_block_tag_t * tag;
9852 int nr = 0;
9854 tagp = &bh->b_data[sizeof(journal_header_t)];
9856 while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
9857 tag = (journal_block_tag_t *) tagp;
9859 nr++;
9860 tagp += sizeof(journal_block_tag_t);
9861 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
9862 tagp += 16;
9864 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
9865 break;
9868 return nr;
9872 /* Make sure we wrap around the log correctly! */
9873 #define wrap(journal, var) \
9874 do { \
9875 if (var >= (journal)->j_last) \
9876 var -= ((journal)->j_last - (journal)->j_first); \
9877 } while (0)
9880 * int journal_recover(journal_t *journal) - recovers a on-disk journal
9881 * @journal: the journal to recover
9883 * The primary function for recovering the log contents when mounting a
9884 * journaled device.
9886 * Recovery is done in three passes. In the first pass, we look for the
9887 * end of the log. In the second, we assemble the list of revoke
9888 * blocks. In the third and final pass, we replay any un-revoked blocks
9889 * in the log.
9891 int journal_recover(journal_t *journal)
9893 int err;
9894 journal_superblock_t * sb;
9896 struct recovery_info info;
9898 memset(&info, 0, sizeof(info));
9899 sb = journal->j_superblock;
9902 * The journal superblock's s_start field (the current log head)
9903 * is always zero if, and only if, the journal was cleanly
9904 * unmounted.
9907 if (!sb->s_start) {
9908 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
9909 return 0;
9912 err = do_one_pass(journal, &info, PASS_SCAN);
9913 if (!err)
9914 err = do_one_pass(journal, &info, PASS_REVOKE);
9915 if (!err)
9916 err = do_one_pass(journal, &info, PASS_REPLAY);
9918 /* Restart the log at the next transaction ID, thus invalidating
9919 * any existing commit records in the log. */
9920 journal->j_transaction_sequence = ++info.end_transaction;
9922 journal_clear_revoke(journal);
9923 sync_blockdev(journal->j_fs_dev);
9924 return err;
9927 static int do_one_pass(journal_t *journal,
9928 struct recovery_info *info, enum passtype pass)
9930 unsigned int first_commit_ID, next_commit_ID;
9931 unsigned long next_log_block;
9932 int err, success = 0;
9933 journal_superblock_t * sb;
9934 journal_header_t * tmp;
9935 struct buffer_head * bh;
9936 unsigned int sequence;
9937 int blocktype;
9939 /* Precompute the maximum metadata descriptors in a descriptor block */
9940 int MAX_BLOCKS_PER_DESC;
9941 MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
9942 / sizeof(journal_block_tag_t));
9945 * First thing is to establish what we expect to find in the log
9946 * (in terms of transaction IDs), and where (in terms of log
9947 * block offsets): query the superblock.
9950 sb = journal->j_superblock;
9951 next_commit_ID = ntohl(sb->s_sequence);
9952 next_log_block = ntohl(sb->s_start);
9954 first_commit_ID = next_commit_ID;
9955 if (pass == PASS_SCAN)
9956 info->start_transaction = first_commit_ID;
9959 * Now we walk through the log, transaction by transaction,
9960 * making sure that each transaction has a commit block in the
9961 * expected place. Each complete transaction gets replayed back
9962 * into the main filesystem.
9965 while (1) {
9966 int flags;
9967 char * tagp;
9968 journal_block_tag_t * tag;
9969 struct buffer_head * obh;
9970 struct buffer_head * nbh;
9972 /* If we already know where to stop the log traversal,
9973 * check right now that we haven't gone past the end of
9974 * the log. */
9976 if (pass != PASS_SCAN)
9977 if (tid_geq(next_commit_ID, info->end_transaction))
9978 break;
9980 /* Skip over each chunk of the transaction looking
9981 * either the next descriptor block or the final commit
9982 * record. */
9984 err = jread(&bh, journal, next_log_block);
9985 if (err)
9986 goto failed;
9988 next_log_block++;
9989 wrap(journal, next_log_block);
9991 /* What kind of buffer is it?
9993 * If it is a descriptor block, check that it has the
9994 * expected sequence number. Otherwise, we're all done
9995 * here. */
9997 tmp = (journal_header_t *)bh->b_data;
9999 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
10000 brelse(bh);
10001 break;
10004 blocktype = ntohl(tmp->h_blocktype);
10005 sequence = ntohl(tmp->h_sequence);
10007 if (sequence != next_commit_ID) {
10008 brelse(bh);
10009 break;
10012 /* OK, we have a valid descriptor block which matches
10013 * all of the sequence number checks. What are we going
10014 * to do with it? That depends on the pass... */
10016 switch (blocktype) {
10017 case JFS_DESCRIPTOR_BLOCK:
10018 /* If it is a valid descriptor block, replay it
10019 * in pass REPLAY; otherwise, just skip over the
10020 * blocks it describes. */
10021 if (pass != PASS_REPLAY) {
10022 next_log_block +=
10023 count_tags(bh, journal->j_blocksize);
10024 wrap(journal, next_log_block);
10025 brelse(bh);
10026 continue;
10029 /* A descriptor block: we can now write all of
10030 * the data blocks. Yay, useful work is finally
10031 * getting done here! */
10033 tagp = &bh->b_data[sizeof(journal_header_t)];
10034 while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
10035 <= journal->j_blocksize) {
10036 unsigned long io_block;
10038 tag = (journal_block_tag_t *) tagp;
10039 flags = ntohl(tag->t_flags);
10041 io_block = next_log_block++;
10042 wrap(journal, next_log_block);
10043 err = jread(&obh, journal, io_block);
10044 if (err) {
10045 /* Recover what we can, but
10046 * report failure at the end. */
10047 success = err;
10048 printf("JBD: IO error %d recovering "
10049 "block %ld in log\n",
10050 err, io_block);
10051 } else {
10052 unsigned long blocknr;
10054 blocknr = ntohl(tag->t_blocknr);
10056 /* If the block has been
10057 * revoked, then we're all done
10058 * here. */
10059 if (journal_test_revoke
10060 (journal, blocknr,
10061 next_commit_ID)) {
10062 brelse(obh);
10063 ++info->nr_revoke_hits;
10064 goto skip_write;
10067 /* Find a buffer for the new
10068 * data being restored */
10069 nbh = getblk(journal->j_fs_dev,
10070 blocknr,
10071 journal->j_blocksize);
10072 if (nbh == NULL) {
10073 printf("JBD: Out of memory "
10074 "during recovery.\n");
10075 err = -ENOMEM;
10076 brelse(bh);
10077 brelse(obh);
10078 goto failed;
10081 lock_buffer(nbh);
10082 memcpy(nbh->b_data, obh->b_data,
10083 journal->j_blocksize);
10084 if (flags & JFS_FLAG_ESCAPE) {
10085 *((unsigned int *)bh->b_data) =
10086 htonl(JFS_MAGIC_NUMBER);
10089 mark_buffer_uptodate(nbh, 1);
10090 mark_buffer_dirty(nbh);
10091 ++info->nr_replays;
10092 /* ll_rw_block(WRITE, 1, &nbh); */
10093 unlock_buffer(nbh);
10094 brelse(obh);
10095 brelse(nbh);
10098 skip_write:
10099 tagp += sizeof(journal_block_tag_t);
10100 if (!(flags & JFS_FLAG_SAME_UUID))
10101 tagp += 16;
10103 if (flags & JFS_FLAG_LAST_TAG)
10104 break;
10107 brelse(bh);
10108 continue;
10110 case JFS_COMMIT_BLOCK:
10111 /* Found an expected commit block: not much to
10112 * do other than move on to the next sequence
10113 * number. */
10114 brelse(bh);
10115 next_commit_ID++;
10116 continue;
10118 case JFS_REVOKE_BLOCK:
10119 /* If we aren't in the REVOKE pass, then we can
10120 * just skip over this block. */
10121 if (pass != PASS_REVOKE) {
10122 brelse(bh);
10123 continue;
10126 err = scan_revoke_records(journal, bh,
10127 next_commit_ID, info);
10128 brelse(bh);
10129 if (err)
10130 goto failed;
10131 continue;
10133 default:
10134 goto done;
10138 done:
10140 * We broke out of the log scan loop: either we came to the
10141 * known end of the log or we found an unexpected block in the
10142 * log. If the latter happened, then we know that the "current"
10143 * transaction marks the end of the valid log.
10146 if (pass == PASS_SCAN)
10147 info->end_transaction = next_commit_ID;
10148 else {
10149 /* It's really bad news if different passes end up at
10150 * different places (but possible due to IO errors). */
10151 if (info->end_transaction != next_commit_ID) {
10152 printf("JBD: recovery pass %d ended at "
10153 "transaction %u, expected %u\n",
10154 pass, next_commit_ID, info->end_transaction);
10155 if (!success)
10156 success = -EIO;
10160 return success;
10162 failed:
10163 return err;
10167 /* Scan a revoke record, marking all blocks mentioned as revoked. */
10169 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
10170 tid_t sequence, struct recovery_info *info)
10172 journal_revoke_header_t *header;
10173 int offset, max;
10175 header = (journal_revoke_header_t *) bh->b_data;
10176 offset = sizeof(journal_revoke_header_t);
10177 max = ntohl(header->r_count);
10179 while (offset < max) {
10180 unsigned long blocknr;
10181 int err;
10183 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
10184 offset += 4;
10185 err = journal_set_revoke(journal, blocknr, sequence);
10186 if (err)
10187 return err;
10188 ++info->nr_revokes;
10190 return 0;
10195 * rehash.c --- rebuild hash tree directories
10197 * This algorithm is designed for simplicity of implementation and to
10198 * pack the directory as much as possible. It however requires twice
10199 * as much memory as the size of the directory. The maximum size
10200 * directory supported using a 4k blocksize is roughly a gigabyte, and
10201 * so there may very well be problems with machines that don't have
10202 * virtual memory, and obscenely large directories.
10204 * An alternate algorithm which is much more disk intensive could be
10205 * written, and probably will need to be written in the future. The
10206 * design goals of such an algorithm are: (a) use (roughly) constant
10207 * amounts of memory, no matter how large the directory, (b) the
10208 * directory must be safe at all times, even if e2fsck is interrupted
10209 * in the middle, (c) we must use minimal amounts of extra disk
10210 * blocks. This pretty much requires an incremental approach, where
10211 * we are reading from one part of the directory, and inserting into
10212 * the front half. So the algorithm will have to keep track of a
10213 * moving block boundary between the new tree and the old tree, and
10214 * files will need to be moved from the old directory and inserted
10215 * into the new tree. If the new directory requires space which isn't
10216 * yet available, blocks from the beginning part of the old directory
10217 * may need to be moved to the end of the directory to make room for
10218 * the new tree:
10220 * --------------------------------------------------------
10221 * | new tree | | old tree |
10222 * --------------------------------------------------------
10223 * ^ ptr ^ptr
10224 * tail new head old
10226 * This is going to be a pain in the tuckus to implement, and will
10227 * require a lot more disk accesses. So I'm going to skip it for now;
10228 * it's only really going to be an issue for really, really big
10229 * filesystems (when we reach the level of tens of millions of files
10230 * in a single directory). It will probably be easier to simply
10231 * require that e2fsck use VM first.
10234 struct fill_dir_struct {
10235 char *buf;
10236 struct ext2_inode *inode;
10237 int err;
10238 e2fsck_t ctx;
10239 struct hash_entry *harray;
10240 int max_array, num_array;
10241 int dir_size;
10242 int compress;
10243 ino_t parent;
10246 struct hash_entry {
10247 ext2_dirhash_t hash;
10248 ext2_dirhash_t minor_hash;
10249 struct ext2_dir_entry *dir;
10252 struct out_dir {
10253 int num;
10254 int max;
10255 char *buf;
10256 ext2_dirhash_t *hashes;
10259 static int fill_dir_block(ext2_filsys fs,
10260 blk_t *block_nr,
10261 e2_blkcnt_t blockcnt,
10262 blk_t ref_block FSCK_ATTR((unused)),
10263 int ref_offset FSCK_ATTR((unused)),
10264 void *priv_data)
10266 struct fill_dir_struct *fd = (struct fill_dir_struct *) priv_data;
10267 struct hash_entry *new_array, *ent;
10268 struct ext2_dir_entry *dirent;
10269 char *dir;
10270 unsigned int offset, dir_offset;
10272 if (blockcnt < 0)
10273 return 0;
10275 offset = blockcnt * fs->blocksize;
10276 if (offset + fs->blocksize > fd->inode->i_size) {
10277 fd->err = EXT2_ET_DIR_CORRUPTED;
10278 return BLOCK_ABORT;
10280 dir = (fd->buf+offset);
10281 if (HOLE_BLKADDR(*block_nr)) {
10282 memset(dir, 0, fs->blocksize);
10283 dirent = (struct ext2_dir_entry *) dir;
10284 dirent->rec_len = fs->blocksize;
10285 } else {
10286 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
10287 if (fd->err)
10288 return BLOCK_ABORT;
10290 /* While the directory block is "hot", index it. */
10291 dir_offset = 0;
10292 while (dir_offset < fs->blocksize) {
10293 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
10294 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
10295 (dirent->rec_len < 8) ||
10296 ((dirent->rec_len % 4) != 0) ||
10297 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
10298 fd->err = EXT2_ET_DIR_CORRUPTED;
10299 return BLOCK_ABORT;
10301 dir_offset += dirent->rec_len;
10302 if (dirent->inode == 0)
10303 continue;
10304 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
10305 (dirent->name[0] == '.'))
10306 continue;
10307 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
10308 (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
10309 fd->parent = dirent->inode;
10310 continue;
10312 if (fd->num_array >= fd->max_array) {
10313 new_array = xrealloc(fd->harray,
10314 sizeof(struct hash_entry) * (fd->max_array+500));
10315 fd->harray = new_array;
10316 fd->max_array += 500;
10318 ent = fd->harray + fd->num_array++;
10319 ent->dir = dirent;
10320 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
10321 if (fd->compress)
10322 ent->hash = ent->minor_hash = 0;
10323 else {
10324 fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
10325 dirent->name,
10326 dirent->name_len & 0xFF,
10327 fs->super->s_hash_seed,
10328 &ent->hash, &ent->minor_hash);
10329 if (fd->err)
10330 return BLOCK_ABORT;
10334 return 0;
10337 /* Used for sorting the hash entry */
10338 static int name_cmp(const void *a, const void *b)
10340 const struct hash_entry *he_a = (const struct hash_entry *) a;
10341 const struct hash_entry *he_b = (const struct hash_entry *) b;
10342 int ret;
10343 int min_len;
10345 min_len = he_a->dir->name_len;
10346 if (min_len > he_b->dir->name_len)
10347 min_len = he_b->dir->name_len;
10349 ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
10350 if (ret == 0) {
10351 if (he_a->dir->name_len > he_b->dir->name_len)
10352 ret = 1;
10353 else if (he_a->dir->name_len < he_b->dir->name_len)
10354 ret = -1;
10355 else
10356 ret = he_b->dir->inode - he_a->dir->inode;
10358 return ret;
10361 /* Used for sorting the hash entry */
10362 static int hash_cmp(const void *a, const void *b)
10364 const struct hash_entry *he_a = (const struct hash_entry *) a;
10365 const struct hash_entry *he_b = (const struct hash_entry *) b;
10366 int ret;
10368 if (he_a->hash > he_b->hash)
10369 ret = 1;
10370 else if (he_a->hash < he_b->hash)
10371 ret = -1;
10372 else {
10373 if (he_a->minor_hash > he_b->minor_hash)
10374 ret = 1;
10375 else if (he_a->minor_hash < he_b->minor_hash)
10376 ret = -1;
10377 else
10378 ret = name_cmp(a, b);
10380 return ret;
10383 static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
10384 int blocks)
10386 void *new_mem;
10388 if (outdir->max) {
10389 new_mem = xrealloc(outdir->buf, blocks * fs->blocksize);
10390 outdir->buf = new_mem;
10391 new_mem = xrealloc(outdir->hashes,
10392 blocks * sizeof(ext2_dirhash_t));
10393 outdir->hashes = new_mem;
10394 } else {
10395 outdir->buf = xmalloc(blocks * fs->blocksize);
10396 outdir->hashes = xmalloc(blocks * sizeof(ext2_dirhash_t));
10397 outdir->num = 0;
10399 outdir->max = blocks;
10400 return 0;
10403 static void free_out_dir(struct out_dir *outdir)
10405 free(outdir->buf);
10406 free(outdir->hashes);
10407 outdir->max = 0;
10408 outdir->num =0;
10411 static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
10412 char ** ret)
10414 errcode_t retval;
10416 if (outdir->num >= outdir->max) {
10417 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
10418 if (retval)
10419 return retval;
10421 *ret = outdir->buf + (outdir->num++ * fs->blocksize);
10422 memset(*ret, 0, fs->blocksize);
10423 return 0;
10427 * This function is used to make a unique filename. We do this by
10428 * appending ~0, and then incrementing the number. However, we cannot
10429 * expand the length of the filename beyond the padding available in
10430 * the directory entry.
10432 static void mutate_name(char *str, __u16 *len)
10434 int i;
10435 __u16 l = *len & 0xFF, h = *len & 0xff00;
10438 * First check to see if it looks the name has been mutated
10439 * already
10441 for (i = l-1; i > 0; i--) {
10442 if (!isdigit(str[i]))
10443 break;
10445 if ((i == l-1) || (str[i] != '~')) {
10446 if (((l-1) & 3) < 2)
10447 l += 2;
10448 else
10449 l = (l+3) & ~3;
10450 str[l-2] = '~';
10451 str[l-1] = '0';
10452 *len = l | h;
10453 return;
10455 for (i = l-1; i >= 0; i--) {
10456 if (isdigit(str[i])) {
10457 if (str[i] == '9')
10458 str[i] = '0';
10459 else {
10460 str[i]++;
10461 return;
10463 continue;
10465 if (i == 1) {
10466 if (str[0] == 'z')
10467 str[0] = 'A';
10468 else if (str[0] == 'Z') {
10469 str[0] = '~';
10470 str[1] = '0';
10471 } else
10472 str[0]++;
10473 } else if (i > 0) {
10474 str[i] = '1';
10475 str[i-1] = '~';
10476 } else {
10477 if (str[0] == '~')
10478 str[0] = 'a';
10479 else
10480 str[0]++;
10482 break;
10486 static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
10487 ext2_ino_t ino,
10488 struct fill_dir_struct *fd)
10490 struct problem_context pctx;
10491 struct hash_entry *ent, *prev;
10492 int i, j;
10493 int fixed = 0;
10494 char new_name[256];
10495 __u16 new_len;
10497 clear_problem_context(&pctx);
10498 pctx.ino = ino;
10500 for (i=1; i < fd->num_array; i++) {
10501 ent = fd->harray + i;
10502 prev = ent - 1;
10503 if (!ent->dir->inode ||
10504 ((ent->dir->name_len & 0xFF) !=
10505 (prev->dir->name_len & 0xFF)) ||
10506 (strncmp(ent->dir->name, prev->dir->name,
10507 ent->dir->name_len & 0xFF)))
10508 continue;
10509 pctx.dirent = ent->dir;
10510 if ((ent->dir->inode == prev->dir->inode) &&
10511 fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
10512 e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
10513 ent->dir->inode = 0;
10514 fixed++;
10515 continue;
10517 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
10518 new_len = ent->dir->name_len;
10519 mutate_name(new_name, &new_len);
10520 for (j=0; j < fd->num_array; j++) {
10521 if ((i==j) ||
10522 ((ent->dir->name_len & 0xFF) !=
10523 (fd->harray[j].dir->name_len & 0xFF)) ||
10524 (strncmp(new_name, fd->harray[j].dir->name,
10525 new_len & 0xFF)))
10526 continue;
10527 mutate_name(new_name, &new_len);
10529 j = -1;
10531 new_name[new_len & 0xFF] = 0;
10532 pctx.str = new_name;
10533 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
10534 memcpy(ent->dir->name, new_name, new_len & 0xFF);
10535 ent->dir->name_len = new_len;
10536 ext2fs_dirhash(fs->super->s_def_hash_version,
10537 ent->dir->name,
10538 ent->dir->name_len & 0xFF,
10539 fs->super->s_hash_seed,
10540 &ent->hash, &ent->minor_hash);
10541 fixed++;
10544 return fixed;
10548 static errcode_t copy_dir_entries(ext2_filsys fs,
10549 struct fill_dir_struct *fd,
10550 struct out_dir *outdir)
10552 errcode_t retval;
10553 char *block_start;
10554 struct hash_entry *ent;
10555 struct ext2_dir_entry *dirent;
10556 int i, rec_len, left;
10557 ext2_dirhash_t prev_hash;
10558 int offset;
10560 outdir->max = 0;
10561 retval = alloc_size_dir(fs, outdir,
10562 (fd->dir_size / fs->blocksize) + 2);
10563 if (retval)
10564 return retval;
10565 outdir->num = fd->compress ? 0 : 1;
10566 offset = 0;
10567 outdir->hashes[0] = 0;
10568 prev_hash = 1;
10569 if ((retval = get_next_block(fs, outdir, &block_start)))
10570 return retval;
10571 dirent = (struct ext2_dir_entry *) block_start;
10572 left = fs->blocksize;
10573 for (i=0; i < fd->num_array; i++) {
10574 ent = fd->harray + i;
10575 if (ent->dir->inode == 0)
10576 continue;
10577 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
10578 if (rec_len > left) {
10579 if (left)
10580 dirent->rec_len += left;
10581 if ((retval = get_next_block(fs, outdir,
10582 &block_start)))
10583 return retval;
10584 offset = 0;
10586 left = fs->blocksize - offset;
10587 dirent = (struct ext2_dir_entry *) (block_start + offset);
10588 if (offset == 0) {
10589 if (ent->hash == prev_hash)
10590 outdir->hashes[outdir->num-1] = ent->hash | 1;
10591 else
10592 outdir->hashes[outdir->num-1] = ent->hash;
10594 dirent->inode = ent->dir->inode;
10595 dirent->name_len = ent->dir->name_len;
10596 dirent->rec_len = rec_len;
10597 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
10598 offset += rec_len;
10599 left -= rec_len;
10600 if (left < 12) {
10601 dirent->rec_len += left;
10602 offset += left;
10603 left = 0;
10605 prev_hash = ent->hash;
10607 if (left)
10608 dirent->rec_len += left;
10610 return 0;
10614 static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
10615 ext2_ino_t ino, ext2_ino_t parent)
10617 struct ext2_dir_entry *dir;
10618 struct ext2_dx_root_info *root;
10619 struct ext2_dx_countlimit *limits;
10620 int filetype = 0;
10622 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
10623 filetype = EXT2_FT_DIR << 8;
10625 memset(buf, 0, fs->blocksize);
10626 dir = (struct ext2_dir_entry *) buf;
10627 dir->inode = ino;
10628 dir->name[0] = '.';
10629 dir->name_len = 1 | filetype;
10630 dir->rec_len = 12;
10631 dir = (struct ext2_dir_entry *) (buf + 12);
10632 dir->inode = parent;
10633 dir->name[0] = '.';
10634 dir->name[1] = '.';
10635 dir->name_len = 2 | filetype;
10636 dir->rec_len = fs->blocksize - 12;
10638 root = (struct ext2_dx_root_info *) (buf+24);
10639 root->reserved_zero = 0;
10640 root->hash_version = fs->super->s_def_hash_version;
10641 root->info_length = 8;
10642 root->indirect_levels = 0;
10643 root->unused_flags = 0;
10645 limits = (struct ext2_dx_countlimit *) (buf+32);
10646 limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
10647 limits->count = 0;
10649 return root;
10653 static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
10655 struct ext2_dir_entry *dir;
10656 struct ext2_dx_countlimit *limits;
10658 memset(buf, 0, fs->blocksize);
10659 dir = (struct ext2_dir_entry *) buf;
10660 dir->inode = 0;
10661 dir->rec_len = fs->blocksize;
10663 limits = (struct ext2_dx_countlimit *) (buf+8);
10664 limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
10665 limits->count = 0;
10667 return (struct ext2_dx_entry *) limits;
10671 * This function takes the leaf nodes which have been written in
10672 * outdir, and populates the root node and any necessary interior nodes.
10674 static errcode_t calculate_tree(ext2_filsys fs,
10675 struct out_dir *outdir,
10676 ext2_ino_t ino,
10677 ext2_ino_t parent)
10679 struct ext2_dx_root_info *root_info;
10680 struct ext2_dx_entry *root, *dx_ent = NULL;
10681 struct ext2_dx_countlimit *root_limit, *limit;
10682 errcode_t retval;
10683 char * block_start;
10684 int i, c1, c2, nblks;
10685 int limit_offset, root_offset;
10687 root_info = set_root_node(fs, outdir->buf, ino, parent);
10688 root_offset = limit_offset = ((char *) root_info - outdir->buf) +
10689 root_info->info_length;
10690 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10691 c1 = root_limit->limit;
10692 nblks = outdir->num;
10694 /* Write out the pointer blocks */
10695 if (nblks-1 <= c1) {
10696 /* Just write out the root block, and we're done */
10697 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
10698 for (i=1; i < nblks; i++) {
10699 root->block = ext2fs_cpu_to_le32(i);
10700 if (i != 1)
10701 root->hash =
10702 ext2fs_cpu_to_le32(outdir->hashes[i]);
10703 root++;
10704 c1--;
10706 } else {
10707 c2 = 0;
10708 limit = 0;
10709 root_info->indirect_levels = 1;
10710 for (i=1; i < nblks; i++) {
10711 if (c1 == 0)
10712 return ENOSPC;
10713 if (c2 == 0) {
10714 if (limit)
10715 limit->limit = limit->count =
10716 ext2fs_cpu_to_le16(limit->limit);
10717 root = (struct ext2_dx_entry *)
10718 (outdir->buf + root_offset);
10719 root->block = ext2fs_cpu_to_le32(outdir->num);
10720 if (i != 1)
10721 root->hash =
10722 ext2fs_cpu_to_le32(outdir->hashes[i]);
10723 if ((retval = get_next_block(fs, outdir,
10724 &block_start)))
10725 return retval;
10726 dx_ent = set_int_node(fs, block_start);
10727 limit = (struct ext2_dx_countlimit *) dx_ent;
10728 c2 = limit->limit;
10729 root_offset += sizeof(struct ext2_dx_entry);
10730 c1--;
10732 dx_ent->block = ext2fs_cpu_to_le32(i);
10733 if (c2 != limit->limit)
10734 dx_ent->hash =
10735 ext2fs_cpu_to_le32(outdir->hashes[i]);
10736 dx_ent++;
10737 c2--;
10739 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
10740 limit->limit = ext2fs_cpu_to_le16(limit->limit);
10742 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10743 root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
10744 root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
10746 return 0;
10749 struct write_dir_struct {
10750 struct out_dir *outdir;
10751 errcode_t err;
10752 e2fsck_t ctx;
10753 int cleared;
10757 * Helper function which writes out a directory block.
10759 static int write_dir_block(ext2_filsys fs,
10760 blk_t *block_nr,
10761 e2_blkcnt_t blockcnt,
10762 blk_t ref_block FSCK_ATTR((unused)),
10763 int ref_offset FSCK_ATTR((unused)),
10764 void *priv_data)
10766 struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
10767 blk_t blk;
10768 char *dir;
10770 if (*block_nr == 0)
10771 return 0;
10772 if (blockcnt >= wd->outdir->num) {
10773 e2fsck_read_bitmaps(wd->ctx);
10774 blk = *block_nr;
10775 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
10776 ext2fs_block_alloc_stats(fs, blk, -1);
10777 *block_nr = 0;
10778 wd->cleared++;
10779 return BLOCK_CHANGED;
10781 if (blockcnt < 0)
10782 return 0;
10784 dir = wd->outdir->buf + (blockcnt * fs->blocksize);
10785 wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
10786 if (wd->err)
10787 return BLOCK_ABORT;
10788 return 0;
10791 static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
10792 struct out_dir *outdir,
10793 ext2_ino_t ino, int compress)
10795 struct write_dir_struct wd;
10796 errcode_t retval;
10797 struct ext2_inode inode;
10799 retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
10800 if (retval)
10801 return retval;
10803 wd.outdir = outdir;
10804 wd.err = 0;
10805 wd.ctx = ctx;
10806 wd.cleared = 0;
10808 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10809 write_dir_block, &wd);
10810 if (retval)
10811 return retval;
10812 if (wd.err)
10813 return wd.err;
10815 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10816 if (compress)
10817 inode.i_flags &= ~EXT2_INDEX_FL;
10818 else
10819 inode.i_flags |= EXT2_INDEX_FL;
10820 inode.i_size = outdir->num * fs->blocksize;
10821 inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
10822 e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
10824 return 0;
10827 static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
10829 ext2_filsys fs = ctx->fs;
10830 errcode_t retval;
10831 struct ext2_inode inode;
10832 char *dir_buf = NULL;
10833 struct fill_dir_struct fd;
10834 struct out_dir outdir;
10836 outdir.max = outdir.num = 0;
10837 outdir.buf = 0;
10838 outdir.hashes = 0;
10839 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10841 retval = ENOMEM;
10842 fd.harray = 0;
10843 dir_buf = xmalloc(inode.i_size);
10845 fd.max_array = inode.i_size / 32;
10846 fd.num_array = 0;
10847 fd.harray = xmalloc(fd.max_array * sizeof(struct hash_entry));
10849 fd.ctx = ctx;
10850 fd.buf = dir_buf;
10851 fd.inode = &inode;
10852 fd.err = 0;
10853 fd.dir_size = 0;
10854 fd.compress = 0;
10855 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
10856 (inode.i_size / fs->blocksize) < 2)
10857 fd.compress = 1;
10858 fd.parent = 0;
10860 /* Read in the entire directory into memory */
10861 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10862 fill_dir_block, &fd);
10863 if (fd.err) {
10864 retval = fd.err;
10865 goto errout;
10868 /* Sort the list */
10869 resort:
10870 if (fd.compress)
10871 qsort(fd.harray+2, fd.num_array-2,
10872 sizeof(struct hash_entry), name_cmp);
10873 else
10874 qsort(fd.harray, fd.num_array,
10875 sizeof(struct hash_entry), hash_cmp);
10878 * Look for duplicates
10880 if (duplicate_search_and_fix(ctx, fs, ino, &fd))
10881 goto resort;
10883 if (ctx->options & E2F_OPT_NO) {
10884 retval = 0;
10885 goto errout;
10889 * Copy the directory entries. In a htree directory these
10890 * will become the leaf nodes.
10892 retval = copy_dir_entries(fs, &fd, &outdir);
10893 if (retval)
10894 goto errout;
10896 free(dir_buf); dir_buf = 0;
10898 if (!fd.compress) {
10899 /* Calculate the interior nodes */
10900 retval = calculate_tree(fs, &outdir, ino, fd.parent);
10901 if (retval)
10902 goto errout;
10905 retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
10907 errout:
10908 free(dir_buf);
10909 free(fd.harray);
10911 free_out_dir(&outdir);
10912 return retval;
10915 void e2fsck_rehash_directories(e2fsck_t ctx)
10917 struct problem_context pctx;
10918 struct dir_info *dir;
10919 ext2_u32_iterate iter;
10920 ext2_ino_t ino;
10921 errcode_t retval;
10922 int i, cur, max, all_dirs, dir_index, first = 1;
10924 all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
10926 if (!ctx->dirs_to_hash && !all_dirs)
10927 return;
10929 e2fsck_get_lost_and_found(ctx, 0);
10931 clear_problem_context(&pctx);
10933 dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
10934 cur = 0;
10935 if (all_dirs) {
10936 i = 0;
10937 max = e2fsck_get_num_dirinfo(ctx);
10938 } else {
10939 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
10940 &iter);
10941 if (retval) {
10942 pctx.errcode = retval;
10943 fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
10944 return;
10946 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
10948 while (1) {
10949 if (all_dirs) {
10950 if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
10951 break;
10952 ino = dir->ino;
10953 } else {
10954 if (!ext2fs_u32_list_iterate(iter, &ino))
10955 break;
10957 if (ino == ctx->lost_and_found)
10958 continue;
10959 pctx.dir = ino;
10960 if (first) {
10961 fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
10962 first = 0;
10964 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
10965 if (pctx.errcode) {
10966 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10967 fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
10969 if (ctx->progress && !ctx->progress_fd)
10970 e2fsck_simple_progress(ctx, "Rebuilding directory",
10971 100.0 * (float) (++cur) / (float) max, ino);
10973 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10974 if (!all_dirs)
10975 ext2fs_u32_list_iterate_end(iter);
10977 ext2fs_u32_list_free(ctx->dirs_to_hash);
10978 ctx->dirs_to_hash = 0;
10982 * linux/fs/revoke.c
10984 * Journal revoke routines for the generic filesystem journaling code;
10985 * part of the ext2fs journaling system.
10987 * Revoke is the mechanism used to prevent old log records for deleted
10988 * metadata from being replayed on top of newer data using the same
10989 * blocks. The revoke mechanism is used in two separate places:
10991 * + Commit: during commit we write the entire list of the current
10992 * transaction's revoked blocks to the journal
10994 * + Recovery: during recovery we record the transaction ID of all
10995 * revoked blocks. If there are multiple revoke records in the log
10996 * for a single block, only the last one counts, and if there is a log
10997 * entry for a block beyond the last revoke, then that log entry still
10998 * gets replayed.
11000 * We can get interactions between revokes and new log data within a
11001 * single transaction:
11003 * Block is revoked and then journaled:
11004 * The desired end result is the journaling of the new block, so we
11005 * cancel the revoke before the transaction commits.
11007 * Block is journaled and then revoked:
11008 * The revoke must take precedence over the write of the block, so we
11009 * need either to cancel the journal entry or to write the revoke
11010 * later in the log than the log block. In this case, we choose the
11011 * latter: journaling a block cancels any revoke record for that block
11012 * in the current transaction, so any revoke for that block in the
11013 * transaction must have happened after the block was journaled and so
11014 * the revoke must take precedence.
11016 * Block is revoked and then written as data:
11017 * The data write is allowed to succeed, but the revoke is _not_
11018 * cancelled. We still need to prevent old log records from
11019 * overwriting the new data. We don't even need to clear the revoke
11020 * bit here.
11022 * Revoke information on buffers is a tri-state value:
11024 * RevokeValid clear: no cached revoke status, need to look it up
11025 * RevokeValid set, Revoked clear:
11026 * buffer has not been revoked, and cancel_revoke
11027 * need do nothing.
11028 * RevokeValid set, Revoked set:
11029 * buffer has been revoked.
11032 static kmem_cache_t *revoke_record_cache;
11033 static kmem_cache_t *revoke_table_cache;
11035 /* Each revoke record represents one single revoked block. During
11036 journal replay, this involves recording the transaction ID of the
11037 last transaction to revoke this block. */
11039 struct jbd_revoke_record_s
11041 struct list_head hash;
11042 tid_t sequence; /* Used for recovery only */
11043 unsigned long blocknr;
11047 /* The revoke table is just a simple hash table of revoke records. */
11048 struct jbd_revoke_table_s
11050 /* It is conceivable that we might want a larger hash table
11051 * for recovery. Must be a power of two. */
11052 int hash_size;
11053 int hash_shift;
11054 struct list_head *hash_table;
11058 /* Utility functions to maintain the revoke table */
11060 /* Borrowed from buffer.c: this is a tried and tested block hash function */
11061 static int hash(journal_t *journal, unsigned long block)
11063 struct jbd_revoke_table_s *table = journal->j_revoke;
11064 int hash_shift = table->hash_shift;
11066 return ((block << (hash_shift - 6)) ^
11067 (block >> 13) ^
11068 (block << (hash_shift - 12))) & (table->hash_size - 1);
11071 static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
11072 tid_t seq)
11074 struct list_head *hash_list;
11075 struct jbd_revoke_record_s *record;
11077 record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
11078 if (!record)
11079 goto oom;
11081 record->sequence = seq;
11082 record->blocknr = blocknr;
11083 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11084 list_add(&record->hash, hash_list);
11085 return 0;
11087 oom:
11088 return -ENOMEM;
11091 /* Find a revoke record in the journal's hash table. */
11093 static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
11094 unsigned long blocknr)
11096 struct list_head *hash_list;
11097 struct jbd_revoke_record_s *record;
11099 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11101 record = (struct jbd_revoke_record_s *) hash_list->next;
11102 while (&(record->hash) != hash_list) {
11103 if (record->blocknr == blocknr)
11104 return record;
11105 record = (struct jbd_revoke_record_s *) record->hash.next;
11107 return NULL;
11110 int journal_init_revoke_caches(void)
11112 revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
11113 if (revoke_record_cache == 0)
11114 return -ENOMEM;
11116 revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
11117 if (revoke_table_cache == 0) {
11118 do_cache_destroy(revoke_record_cache);
11119 revoke_record_cache = NULL;
11120 return -ENOMEM;
11122 return 0;
11125 void journal_destroy_revoke_caches(void)
11127 do_cache_destroy(revoke_record_cache);
11128 revoke_record_cache = 0;
11129 do_cache_destroy(revoke_table_cache);
11130 revoke_table_cache = 0;
11133 /* Initialise the revoke table for a given journal to a given size. */
11135 int journal_init_revoke(journal_t *journal, int hash_size)
11137 int shift, tmp;
11139 journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
11140 if (!journal->j_revoke)
11141 return -ENOMEM;
11143 /* Check that the hash_size is a power of two */
11144 journal->j_revoke->hash_size = hash_size;
11146 shift = 0;
11147 tmp = hash_size;
11148 while ((tmp >>= 1UL) != 0UL)
11149 shift++;
11150 journal->j_revoke->hash_shift = shift;
11152 journal->j_revoke->hash_table = xmalloc(hash_size * sizeof(struct list_head));
11154 for (tmp = 0; tmp < hash_size; tmp++)
11155 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
11157 return 0;
11160 /* Destoy a journal's revoke table. The table must already be empty! */
11162 void journal_destroy_revoke(journal_t *journal)
11164 struct jbd_revoke_table_s *table;
11165 struct list_head *hash_list;
11166 int i;
11168 table = journal->j_revoke;
11169 if (!table)
11170 return;
11172 for (i=0; i<table->hash_size; i++) {
11173 hash_list = &table->hash_table[i];
11176 free(table->hash_table);
11177 free(table);
11178 journal->j_revoke = NULL;
11182 * Revoke support for recovery.
11184 * Recovery needs to be able to:
11186 * record all revoke records, including the tid of the latest instance
11187 * of each revoke in the journal
11189 * check whether a given block in a given transaction should be replayed
11190 * (ie. has not been revoked by a revoke record in that or a subsequent
11191 * transaction)
11193 * empty the revoke table after recovery.
11197 * First, setting revoke records. We create a new revoke record for
11198 * every block ever revoked in the log as we scan it for recovery, and
11199 * we update the existing records if we find multiple revokes for a
11200 * single block.
11203 int journal_set_revoke(journal_t *journal, unsigned long blocknr,
11204 tid_t sequence)
11206 struct jbd_revoke_record_s *record;
11208 record = find_revoke_record(journal, blocknr);
11209 if (record) {
11210 /* If we have multiple occurences, only record the
11211 * latest sequence number in the hashed record */
11212 if (tid_gt(sequence, record->sequence))
11213 record->sequence = sequence;
11214 return 0;
11216 return insert_revoke_hash(journal, blocknr, sequence);
11220 * Test revoke records. For a given block referenced in the log, has
11221 * that block been revoked? A revoke record with a given transaction
11222 * sequence number revokes all blocks in that transaction and earlier
11223 * ones, but later transactions still need replayed.
11226 int journal_test_revoke(journal_t *journal, unsigned long blocknr,
11227 tid_t sequence)
11229 struct jbd_revoke_record_s *record;
11231 record = find_revoke_record(journal, blocknr);
11232 if (!record)
11233 return 0;
11234 if (tid_gt(sequence, record->sequence))
11235 return 0;
11236 return 1;
11240 * Finally, once recovery is over, we need to clear the revoke table so
11241 * that it can be reused by the running filesystem.
11244 void journal_clear_revoke(journal_t *journal)
11246 int i;
11247 struct list_head *hash_list;
11248 struct jbd_revoke_record_s *record;
11249 struct jbd_revoke_table_s *revoke_var;
11251 revoke_var = journal->j_revoke;
11253 for (i = 0; i < revoke_var->hash_size; i++) {
11254 hash_list = &revoke_var->hash_table[i];
11255 while (!list_empty(hash_list)) {
11256 record = (struct jbd_revoke_record_s*) hash_list->next;
11257 list_del(&record->hash);
11258 free(record);
11264 * e2fsck.c - superblock checks
11267 #define MIN_CHECK 1
11268 #define MAX_CHECK 2
11270 static void check_super_value(e2fsck_t ctx, const char *descr,
11271 unsigned long value, int flags,
11272 unsigned long min_val, unsigned long max_val)
11274 struct problem_context pctx;
11276 if (((flags & MIN_CHECK) && (value < min_val)) ||
11277 ((flags & MAX_CHECK) && (value > max_val))) {
11278 clear_problem_context(&pctx);
11279 pctx.num = value;
11280 pctx.str = descr;
11281 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11282 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11287 * This routine may get stubbed out in special compilations of the
11288 * e2fsck code..
11290 #ifndef EXT2_SPECIAL_DEVICE_SIZE
11291 static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
11293 return (ext2fs_get_device_size(ctx->filesystem_name,
11294 EXT2_BLOCK_SIZE(ctx->fs->super),
11295 &ctx->num_blocks));
11297 #endif
11300 * helper function to release an inode
11302 struct process_block_struct {
11303 e2fsck_t ctx;
11304 char *buf;
11305 struct problem_context *pctx;
11306 int truncating;
11307 int truncate_offset;
11308 e2_blkcnt_t truncate_block;
11309 int truncated_blocks;
11310 int abort;
11311 errcode_t errcode;
11314 static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
11315 e2_blkcnt_t blockcnt,
11316 blk_t ref_blk FSCK_ATTR((unused)),
11317 int ref_offset FSCK_ATTR((unused)),
11318 void *priv_data)
11320 struct process_block_struct *pb;
11321 e2fsck_t ctx;
11322 struct problem_context *pctx;
11323 blk_t blk = *block_nr;
11324 int retval = 0;
11326 pb = (struct process_block_struct *) priv_data;
11327 ctx = pb->ctx;
11328 pctx = pb->pctx;
11330 pctx->blk = blk;
11331 pctx->blkcount = blockcnt;
11333 if (HOLE_BLKADDR(blk))
11334 return 0;
11336 if ((blk < fs->super->s_first_data_block) ||
11337 (blk >= fs->super->s_blocks_count)) {
11338 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
11339 return_abort:
11340 pb->abort = 1;
11341 return BLOCK_ABORT;
11344 if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
11345 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
11346 goto return_abort;
11350 * If we are deleting an orphan, then we leave the fields alone.
11351 * If we are truncating an orphan, then update the inode fields
11352 * and clean up any partial block data.
11354 if (pb->truncating) {
11356 * We only remove indirect blocks if they are
11357 * completely empty.
11359 if (blockcnt < 0) {
11360 int i, limit;
11361 blk_t *bp;
11363 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11364 pb->buf);
11365 if (pb->errcode)
11366 goto return_abort;
11368 limit = fs->blocksize >> 2;
11369 for (i = 0, bp = (blk_t *) pb->buf;
11370 i < limit; i++, bp++)
11371 if (*bp)
11372 return 0;
11375 * We don't remove direct blocks until we've reached
11376 * the truncation block.
11378 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
11379 return 0;
11381 * If part of the last block needs truncating, we do
11382 * it here.
11384 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
11385 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11386 pb->buf);
11387 if (pb->errcode)
11388 goto return_abort;
11389 memset(pb->buf + pb->truncate_offset, 0,
11390 fs->blocksize - pb->truncate_offset);
11391 pb->errcode = io_channel_write_blk(fs->io, blk, 1,
11392 pb->buf);
11393 if (pb->errcode)
11394 goto return_abort;
11396 pb->truncated_blocks++;
11397 *block_nr = 0;
11398 retval |= BLOCK_CHANGED;
11401 ext2fs_block_alloc_stats(fs, blk, -1);
11402 return retval;
11406 * This function releases an inode. Returns 1 if an inconsistency was
11407 * found. If the inode has a link count, then it is being truncated and
11408 * not deleted.
11410 static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
11411 struct ext2_inode *inode, char *block_buf,
11412 struct problem_context *pctx)
11414 struct process_block_struct pb;
11415 ext2_filsys fs = ctx->fs;
11416 errcode_t retval;
11417 __u32 count;
11419 if (!ext2fs_inode_has_valid_blocks(inode))
11420 return 0;
11422 pb.buf = block_buf + 3 * ctx->fs->blocksize;
11423 pb.ctx = ctx;
11424 pb.abort = 0;
11425 pb.errcode = 0;
11426 pb.pctx = pctx;
11427 if (inode->i_links_count) {
11428 pb.truncating = 1;
11429 pb.truncate_block = (e2_blkcnt_t)
11430 ((((long long)inode->i_size_high << 32) +
11431 inode->i_size + fs->blocksize - 1) /
11432 fs->blocksize);
11433 pb.truncate_offset = inode->i_size % fs->blocksize;
11434 } else {
11435 pb.truncating = 0;
11436 pb.truncate_block = 0;
11437 pb.truncate_offset = 0;
11439 pb.truncated_blocks = 0;
11440 retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
11441 block_buf, release_inode_block, &pb);
11442 if (retval) {
11443 bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
11444 ino);
11445 return 1;
11447 if (pb.abort)
11448 return 1;
11450 /* Refresh the inode since ext2fs_block_iterate may have changed it */
11451 e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
11453 if (pb.truncated_blocks)
11454 inode->i_blocks -= pb.truncated_blocks *
11455 (fs->blocksize / 512);
11457 if (inode->i_file_acl) {
11458 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
11459 block_buf, -1, &count);
11460 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
11461 retval = 0;
11462 count = 1;
11464 if (retval) {
11465 bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
11466 ino);
11467 return 1;
11469 if (count == 0)
11470 ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
11471 inode->i_file_acl = 0;
11473 return 0;
11477 * This function releases all of the orphan inodes. It returns 1 if
11478 * it hit some error, and 0 on success.
11480 static int release_orphan_inodes(e2fsck_t ctx)
11482 ext2_filsys fs = ctx->fs;
11483 ext2_ino_t ino, next_ino;
11484 struct ext2_inode inode;
11485 struct problem_context pctx;
11486 char *block_buf;
11488 if ((ino = fs->super->s_last_orphan) == 0)
11489 return 0;
11492 * Win or lose, we won't be using the head of the orphan inode
11493 * list again.
11495 fs->super->s_last_orphan = 0;
11496 ext2fs_mark_super_dirty(fs);
11499 * If the filesystem contains errors, don't run the orphan
11500 * list, since the orphan list can't be trusted; and we're
11501 * going to be running a full e2fsck run anyway...
11503 if (fs->super->s_state & EXT2_ERROR_FS)
11504 return 0;
11506 if ((ino < EXT2_FIRST_INODE(fs->super)) ||
11507 (ino > fs->super->s_inodes_count)) {
11508 clear_problem_context(&pctx);
11509 pctx.ino = ino;
11510 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
11511 return 1;
11514 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
11515 "block iterate buffer");
11516 e2fsck_read_bitmaps(ctx);
11518 while (ino) {
11519 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
11520 clear_problem_context(&pctx);
11521 pctx.ino = ino;
11522 pctx.inode = &inode;
11523 pctx.str = inode.i_links_count ? _("Truncating") :
11524 _("Clearing");
11526 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
11528 next_ino = inode.i_dtime;
11529 if (next_ino &&
11530 ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
11531 (next_ino > fs->super->s_inodes_count))) {
11532 pctx.ino = next_ino;
11533 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
11534 goto return_abort;
11537 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
11538 goto return_abort;
11540 if (!inode.i_links_count) {
11541 ext2fs_inode_alloc_stats2(fs, ino, -1,
11542 LINUX_S_ISDIR(inode.i_mode));
11543 inode.i_dtime = time(NULL);
11544 } else {
11545 inode.i_dtime = 0;
11547 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
11548 ino = next_ino;
11550 ext2fs_free_mem(&block_buf);
11551 return 0;
11552 return_abort:
11553 ext2fs_free_mem(&block_buf);
11554 return 1;
11558 * Check the resize inode to make sure it is sane. We check both for
11559 * the case where on-line resizing is not enabled (in which case the
11560 * resize inode should be cleared) as well as the case where on-line
11561 * resizing is enabled.
11563 static void check_resize_inode(e2fsck_t ctx)
11565 ext2_filsys fs = ctx->fs;
11566 struct ext2_inode inode;
11567 struct problem_context pctx;
11568 int i, j, gdt_off, ind_off;
11569 blk_t blk, pblk, expect;
11570 __u32 *dind_buf = NULL, *ind_buf;
11571 errcode_t retval;
11573 clear_problem_context(&pctx);
11576 * If the resize inode feature isn't set, then
11577 * s_reserved_gdt_blocks must be zero.
11579 if (!(fs->super->s_feature_compat &
11580 EXT2_FEATURE_COMPAT_RESIZE_INO)) {
11581 if (fs->super->s_reserved_gdt_blocks) {
11582 pctx.num = fs->super->s_reserved_gdt_blocks;
11583 if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
11584 &pctx)) {
11585 fs->super->s_reserved_gdt_blocks = 0;
11586 ext2fs_mark_super_dirty(fs);
11591 /* Read the resize inode */
11592 pctx.ino = EXT2_RESIZE_INO;
11593 retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
11594 if (retval) {
11595 if (fs->super->s_feature_compat &
11596 EXT2_FEATURE_COMPAT_RESIZE_INO)
11597 ctx->flags |= E2F_FLAG_RESIZE_INODE;
11598 return;
11602 * If the resize inode feature isn't set, check to make sure
11603 * the resize inode is cleared; then we're done.
11605 if (!(fs->super->s_feature_compat &
11606 EXT2_FEATURE_COMPAT_RESIZE_INO)) {
11607 for (i=0; i < EXT2_N_BLOCKS; i++) {
11608 if (inode.i_block[i])
11609 break;
11611 if ((i < EXT2_N_BLOCKS) &&
11612 fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
11613 memset(&inode, 0, sizeof(inode));
11614 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11615 "clear_resize");
11617 return;
11621 * The resize inode feature is enabled; check to make sure the
11622 * only block in use is the double indirect block
11624 blk = inode.i_block[EXT2_DIND_BLOCK];
11625 for (i=0; i < EXT2_N_BLOCKS; i++) {
11626 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
11627 break;
11629 if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
11630 !(inode.i_mode & LINUX_S_IFREG) ||
11631 (blk < fs->super->s_first_data_block ||
11632 blk >= fs->super->s_blocks_count)) {
11633 resize_inode_invalid:
11634 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
11635 memset(&inode, 0, sizeof(inode));
11636 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11637 "clear_resize");
11638 ctx->flags |= E2F_FLAG_RESIZE_INODE;
11640 if (!(ctx->options & E2F_OPT_READONLY)) {
11641 fs->super->s_state &= ~EXT2_VALID_FS;
11642 ext2fs_mark_super_dirty(fs);
11644 goto cleanup;
11646 dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
11647 "resize dind buffer");
11648 ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
11650 retval = ext2fs_read_ind_block(fs, blk, dind_buf);
11651 if (retval)
11652 goto resize_inode_invalid;
11654 gdt_off = fs->desc_blocks;
11655 pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
11656 for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
11657 i++, gdt_off++, pblk++) {
11658 gdt_off %= fs->blocksize/4;
11659 if (dind_buf[gdt_off] != pblk)
11660 goto resize_inode_invalid;
11661 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
11662 if (retval)
11663 goto resize_inode_invalid;
11664 ind_off = 0;
11665 for (j = 1; j < fs->group_desc_count; j++) {
11666 if (!ext2fs_bg_has_super(fs, j))
11667 continue;
11668 expect = pblk + (j * fs->super->s_blocks_per_group);
11669 if (ind_buf[ind_off] != expect)
11670 goto resize_inode_invalid;
11671 ind_off++;
11675 cleanup:
11676 ext2fs_free_mem(&dind_buf);
11679 static void check_super_block(e2fsck_t ctx)
11681 ext2_filsys fs = ctx->fs;
11682 blk_t first_block, last_block;
11683 struct ext2_super_block *sb = fs->super;
11684 struct ext2_group_desc *gd;
11685 blk_t blocks_per_group = fs->super->s_blocks_per_group;
11686 blk_t bpg_max;
11687 int inodes_per_block;
11688 int ipg_max;
11689 int inode_size;
11690 dgrp_t i;
11691 blk_t should_be;
11692 struct problem_context pctx;
11693 __u32 free_blocks = 0, free_inodes = 0;
11695 inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
11696 ipg_max = inodes_per_block * (blocks_per_group - 4);
11697 if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
11698 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
11699 bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
11700 if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
11701 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
11703 ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11704 sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
11705 ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11706 sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
11707 ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
11708 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
11710 clear_problem_context(&pctx);
11713 * Verify the super block constants...
11715 check_super_value(ctx, "inodes_count", sb->s_inodes_count,
11716 MIN_CHECK, 1, 0);
11717 check_super_value(ctx, "blocks_count", sb->s_blocks_count,
11718 MIN_CHECK, 1, 0);
11719 check_super_value(ctx, "first_data_block", sb->s_first_data_block,
11720 MAX_CHECK, 0, sb->s_blocks_count);
11721 check_super_value(ctx, "log_block_size", sb->s_log_block_size,
11722 MIN_CHECK | MAX_CHECK, 0,
11723 EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
11724 check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
11725 MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
11726 check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
11727 MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
11728 bpg_max);
11729 check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
11730 MIN_CHECK | MAX_CHECK, 8, bpg_max);
11731 check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
11732 MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
11733 check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
11734 MAX_CHECK, 0, sb->s_blocks_count / 2);
11735 check_super_value(ctx, "reserved_gdt_blocks",
11736 sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
11737 fs->blocksize/4);
11738 inode_size = EXT2_INODE_SIZE(sb);
11739 check_super_value(ctx, "inode_size",
11740 inode_size, MIN_CHECK | MAX_CHECK,
11741 EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
11742 if (inode_size & (inode_size - 1)) {
11743 pctx.num = inode_size;
11744 pctx.str = "inode_size";
11745 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11746 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11747 return;
11750 if (!ctx->num_blocks) {
11751 pctx.errcode = e2fsck_get_device_size(ctx);
11752 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
11753 fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
11754 ctx->flags |= E2F_FLAG_ABORT;
11755 return;
11757 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
11758 (ctx->num_blocks < sb->s_blocks_count)) {
11759 pctx.blk = sb->s_blocks_count;
11760 pctx.blk2 = ctx->num_blocks;
11761 if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
11762 ctx->flags |= E2F_FLAG_ABORT;
11763 return;
11768 if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
11769 pctx.blk = EXT2_BLOCK_SIZE(sb);
11770 pctx.blk2 = EXT2_FRAG_SIZE(sb);
11771 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
11772 ctx->flags |= E2F_FLAG_ABORT;
11773 return;
11776 should_be = sb->s_frags_per_group >>
11777 (sb->s_log_block_size - sb->s_log_frag_size);
11778 if (sb->s_blocks_per_group != should_be) {
11779 pctx.blk = sb->s_blocks_per_group;
11780 pctx.blk2 = should_be;
11781 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
11782 ctx->flags |= E2F_FLAG_ABORT;
11783 return;
11786 should_be = (sb->s_log_block_size == 0) ? 1 : 0;
11787 if (sb->s_first_data_block != should_be) {
11788 pctx.blk = sb->s_first_data_block;
11789 pctx.blk2 = should_be;
11790 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
11791 ctx->flags |= E2F_FLAG_ABORT;
11792 return;
11795 should_be = sb->s_inodes_per_group * fs->group_desc_count;
11796 if (sb->s_inodes_count != should_be) {
11797 pctx.ino = sb->s_inodes_count;
11798 pctx.ino2 = should_be;
11799 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
11800 sb->s_inodes_count = should_be;
11801 ext2fs_mark_super_dirty(fs);
11806 * Verify the group descriptors....
11808 first_block = sb->s_first_data_block;
11809 last_block = first_block + blocks_per_group;
11811 for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
11812 pctx.group = i;
11814 if (i == fs->group_desc_count - 1)
11815 last_block = sb->s_blocks_count;
11816 if ((gd->bg_block_bitmap < first_block) ||
11817 (gd->bg_block_bitmap >= last_block)) {
11818 pctx.blk = gd->bg_block_bitmap;
11819 if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
11820 gd->bg_block_bitmap = 0;
11822 if (gd->bg_block_bitmap == 0) {
11823 ctx->invalid_block_bitmap_flag[i]++;
11824 ctx->invalid_bitmaps++;
11826 if ((gd->bg_inode_bitmap < first_block) ||
11827 (gd->bg_inode_bitmap >= last_block)) {
11828 pctx.blk = gd->bg_inode_bitmap;
11829 if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
11830 gd->bg_inode_bitmap = 0;
11832 if (gd->bg_inode_bitmap == 0) {
11833 ctx->invalid_inode_bitmap_flag[i]++;
11834 ctx->invalid_bitmaps++;
11836 if ((gd->bg_inode_table < first_block) ||
11837 ((gd->bg_inode_table +
11838 fs->inode_blocks_per_group - 1) >= last_block)) {
11839 pctx.blk = gd->bg_inode_table;
11840 if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
11841 gd->bg_inode_table = 0;
11843 if (gd->bg_inode_table == 0) {
11844 ctx->invalid_inode_table_flag[i]++;
11845 ctx->invalid_bitmaps++;
11847 free_blocks += gd->bg_free_blocks_count;
11848 free_inodes += gd->bg_free_inodes_count;
11849 first_block += sb->s_blocks_per_group;
11850 last_block += sb->s_blocks_per_group;
11852 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
11853 (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
11854 (gd->bg_used_dirs_count > sb->s_inodes_per_group))
11855 ext2fs_unmark_valid(fs);
11859 * Update the global counts from the block group counts. This
11860 * is needed for an experimental patch which eliminates
11861 * locking the entire filesystem when allocating blocks or
11862 * inodes; if the filesystem is not unmounted cleanly, the
11863 * global counts may not be accurate.
11865 if ((free_blocks != sb->s_free_blocks_count) ||
11866 (free_inodes != sb->s_free_inodes_count)) {
11867 if (ctx->options & E2F_OPT_READONLY)
11868 ext2fs_unmark_valid(fs);
11869 else {
11870 sb->s_free_blocks_count = free_blocks;
11871 sb->s_free_inodes_count = free_inodes;
11872 ext2fs_mark_super_dirty(fs);
11876 if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
11877 (sb->s_free_inodes_count > sb->s_inodes_count))
11878 ext2fs_unmark_valid(fs);
11882 * If we have invalid bitmaps, set the error state of the
11883 * filesystem.
11885 if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
11886 sb->s_state &= ~EXT2_VALID_FS;
11887 ext2fs_mark_super_dirty(fs);
11890 clear_problem_context(&pctx);
11893 * If the UUID field isn't assigned, assign it.
11895 if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
11896 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
11897 generate_uuid(sb->s_uuid);
11898 ext2fs_mark_super_dirty(fs);
11899 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
11903 /* FIXME - HURD support?
11904 * For the Hurd, check to see if the filetype option is set,
11905 * since it doesn't support it.
11907 if (!(ctx->options & E2F_OPT_READONLY) &&
11908 fs->super->s_creator_os == EXT2_OS_HURD &&
11909 (fs->super->s_feature_incompat &
11910 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
11911 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
11912 fs->super->s_feature_incompat &=
11913 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
11914 ext2fs_mark_super_dirty(fs);
11919 * If we have any of the compatibility flags set, we need to have a
11920 * revision 1 filesystem. Most kernels will not check the flags on
11921 * a rev 0 filesystem and we may have corruption issues because of
11922 * the incompatible changes to the filesystem.
11924 if (!(ctx->options & E2F_OPT_READONLY) &&
11925 fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
11926 (fs->super->s_feature_compat ||
11927 fs->super->s_feature_ro_compat ||
11928 fs->super->s_feature_incompat) &&
11929 fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
11930 ext2fs_update_dynamic_rev(fs);
11931 ext2fs_mark_super_dirty(fs);
11934 check_resize_inode(ctx);
11937 * Clean up any orphan inodes, if present.
11939 if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
11940 fs->super->s_state &= ~EXT2_VALID_FS;
11941 ext2fs_mark_super_dirty(fs);
11945 * Move the ext3 journal file, if necessary.
11947 e2fsck_move_ext3_journal(ctx);
11951 * swapfs.c --- byte-swap an ext2 filesystem
11954 #ifdef ENABLE_SWAPFS
11956 struct swap_block_struct {
11957 ext2_ino_t ino;
11958 int isdir;
11959 errcode_t errcode;
11960 char *dir_buf;
11961 struct ext2_inode *inode;
11965 * This is a helper function for block_iterate. We mark all of the
11966 * indirect and direct blocks as changed, so that block_iterate will
11967 * write them out.
11969 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
11970 void *priv_data)
11972 errcode_t retval;
11974 struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
11976 if (sb->isdir && (blockcnt >= 0) && *block_nr) {
11977 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
11978 if (retval) {
11979 sb->errcode = retval;
11980 return BLOCK_ABORT;
11982 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
11983 if (retval) {
11984 sb->errcode = retval;
11985 return BLOCK_ABORT;
11988 if (blockcnt >= 0) {
11989 if (blockcnt < EXT2_NDIR_BLOCKS)
11990 return 0;
11991 return BLOCK_CHANGED;
11993 if (blockcnt == BLOCK_COUNT_IND) {
11994 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
11995 return 0;
11996 return BLOCK_CHANGED;
11998 if (blockcnt == BLOCK_COUNT_DIND) {
11999 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
12000 return 0;
12001 return BLOCK_CHANGED;
12003 if (blockcnt == BLOCK_COUNT_TIND) {
12004 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
12005 return 0;
12006 return BLOCK_CHANGED;
12008 return BLOCK_CHANGED;
12012 * This function is responsible for byte-swapping all of the indirect,
12013 * block pointers. It is also responsible for byte-swapping directories.
12015 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
12016 struct ext2_inode *inode)
12018 errcode_t retval;
12019 struct swap_block_struct sb;
12021 sb.ino = ino;
12022 sb.inode = inode;
12023 sb.dir_buf = block_buf + ctx->fs->blocksize*3;
12024 sb.errcode = 0;
12025 sb.isdir = 0;
12026 if (LINUX_S_ISDIR(inode->i_mode))
12027 sb.isdir = 1;
12029 retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
12030 swap_block, &sb);
12031 if (retval) {
12032 bb_error_msg(_("while calling ext2fs_block_iterate"));
12033 ctx->flags |= E2F_FLAG_ABORT;
12034 return;
12036 if (sb.errcode) {
12037 bb_error_msg(_("while calling iterator function"));
12038 ctx->flags |= E2F_FLAG_ABORT;
12039 return;
12043 static void swap_inodes(e2fsck_t ctx)
12045 ext2_filsys fs = ctx->fs;
12046 dgrp_t group;
12047 unsigned int i;
12048 ext2_ino_t ino = 1;
12049 char *buf, *block_buf;
12050 errcode_t retval;
12051 struct ext2_inode * inode;
12053 e2fsck_use_inode_shortcuts(ctx, 1);
12055 retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
12056 &buf);
12057 if (retval) {
12058 bb_error_msg(_("while allocating inode buffer"));
12059 ctx->flags |= E2F_FLAG_ABORT;
12060 return;
12062 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12063 "block interate buffer");
12064 for (group = 0; group < fs->group_desc_count; group++) {
12065 retval = io_channel_read_blk(fs->io,
12066 fs->group_desc[group].bg_inode_table,
12067 fs->inode_blocks_per_group, buf);
12068 if (retval) {
12069 bb_error_msg(_("while reading inode table (group %d)"),
12070 group);
12071 ctx->flags |= E2F_FLAG_ABORT;
12072 return;
12074 inode = (struct ext2_inode *) buf;
12075 for (i=0; i < fs->super->s_inodes_per_group;
12076 i++, ino++, inode++) {
12077 ctx->stashed_ino = ino;
12078 ctx->stashed_inode = inode;
12080 if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
12081 ext2fs_swap_inode(fs, inode, inode, 0);
12084 * Skip deleted files.
12086 if (inode->i_links_count == 0)
12087 continue;
12089 if (LINUX_S_ISDIR(inode->i_mode) ||
12090 ((inode->i_block[EXT2_IND_BLOCK] ||
12091 inode->i_block[EXT2_DIND_BLOCK] ||
12092 inode->i_block[EXT2_TIND_BLOCK]) &&
12093 ext2fs_inode_has_valid_blocks(inode)))
12094 swap_inode_blocks(ctx, ino, block_buf, inode);
12096 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12097 return;
12099 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12100 ext2fs_swap_inode(fs, inode, inode, 1);
12102 retval = io_channel_write_blk(fs->io,
12103 fs->group_desc[group].bg_inode_table,
12104 fs->inode_blocks_per_group, buf);
12105 if (retval) {
12106 bb_error_msg(_("while writing inode table (group %d)"),
12107 group);
12108 ctx->flags |= E2F_FLAG_ABORT;
12109 return;
12112 ext2fs_free_mem(&buf);
12113 ext2fs_free_mem(&block_buf);
12114 e2fsck_use_inode_shortcuts(ctx, 0);
12115 ext2fs_flush_icache(fs);
12118 #if defined(__powerpc__) && BB_BIG_ENDIAN
12120 * On the PowerPC, the big-endian variant of the ext2 filesystem
12121 * has its bitmaps stored as 32-bit words with bit 0 as the LSB
12122 * of each word. Thus a bitmap with only bit 0 set would be, as
12123 * a string of bytes, 00 00 00 01 00 ...
12124 * To cope with this, we byte-reverse each word of a bitmap if
12125 * we have a big-endian filesystem, that is, if we are *not*
12126 * byte-swapping other word-sized numbers.
12128 #define EXT2_BIG_ENDIAN_BITMAPS
12129 #endif
12131 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12132 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
12134 __u32 *p = (__u32 *) bmap->bitmap;
12135 int n, nbytes = (bmap->end - bmap->start + 7) / 8;
12137 for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
12138 *p = ext2fs_swab32(*p);
12140 #endif
12143 #ifdef ENABLE_SWAPFS
12144 static void swap_filesys(e2fsck_t ctx)
12146 ext2_filsys fs = ctx->fs;
12147 if (!(ctx->options & E2F_OPT_PREEN))
12148 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
12150 /* Byte swap */
12152 if (fs->super->s_mnt_count) {
12153 fprintf(stderr, _("%s: the filesystem must be freshly "
12154 "checked using fsck\n"
12155 "and not mounted before trying to "
12156 "byte-swap it.\n"), ctx->device_name);
12157 ctx->flags |= E2F_FLAG_ABORT;
12158 return;
12160 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
12161 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
12162 EXT2_FLAG_SWAP_BYTES_WRITE);
12163 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
12164 } else {
12165 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
12166 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
12168 swap_inodes(ctx);
12169 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12170 return;
12171 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12172 fs->flags |= EXT2_FLAG_SWAP_BYTES;
12173 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
12174 EXT2_FLAG_SWAP_BYTES_WRITE);
12176 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12177 e2fsck_read_bitmaps(ctx);
12178 ext2fs_swap_bitmap(fs->inode_map);
12179 ext2fs_swap_bitmap(fs->block_map);
12180 fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
12181 #endif
12182 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
12183 ext2fs_flush(fs);
12184 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
12186 #endif /* ENABLE_SWAPFS */
12188 #endif
12191 * util.c --- miscellaneous utilities
12195 void *e2fsck_allocate_memory(e2fsck_t ctx EXT2FS_ATTR((unused)), unsigned int size,
12196 const char *description EXT2FS_ATTR((unused)))
12198 void *ret;
12200 ret = xzalloc(size);
12201 return ret;
12204 static char *string_copy(const char *str, int len)
12206 char *ret;
12208 if (!str)
12209 return NULL;
12210 if (!len)
12211 len = strlen(str);
12212 ret = xmalloc(len+1);
12213 strncpy(ret, str, len);
12214 ret[len] = 0;
12215 return ret;
12218 #ifndef HAVE_CONIO_H
12219 static int read_a_char(void)
12221 char c;
12222 int r;
12223 int fail = 0;
12225 while (1) {
12226 if (e2fsck_global_ctx &&
12227 (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
12228 return 3;
12230 r = read(0, &c, 1);
12231 if (r == 1)
12232 return c;
12233 if (fail++ > 100)
12234 break;
12236 return EOF;
12238 #endif
12240 static int ask_yn(const char * string, int def)
12242 int c;
12243 const char *defstr;
12244 static const char short_yes[] = "yY";
12245 static const char short_no[] = "nN";
12247 #ifdef HAVE_TERMIOS_H
12248 struct termios termios, tmp;
12250 tcgetattr (0, &termios);
12251 tmp = termios;
12252 tmp.c_lflag &= ~(ICANON | ECHO);
12253 tmp.c_cc[VMIN] = 1;
12254 tmp.c_cc[VTIME] = 0;
12255 tcsetattr_stdin_TCSANOW(&tmp);
12256 #endif
12258 if (def == 1)
12259 defstr = "<y>";
12260 else if (def == 0)
12261 defstr = "<n>";
12262 else
12263 defstr = " (y/n)";
12264 printf("%s%s? ", string, defstr);
12265 while (1) {
12266 fflush (stdout);
12267 if ((c = read_a_char()) == EOF)
12268 break;
12269 if (c == 3) {
12270 #ifdef HAVE_TERMIOS_H
12271 tcsetattr_stdin_TCSANOW(&termios);
12272 #endif
12273 if (e2fsck_global_ctx &&
12274 e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
12275 puts("\n");
12276 longjmp(e2fsck_global_ctx->abort_loc, 1);
12278 puts(_("cancelled!\n"));
12279 return 0;
12281 if (strchr(short_yes, (char) c)) {
12282 def = 1;
12283 break;
12285 else if (strchr(short_no, (char) c)) {
12286 def = 0;
12287 break;
12289 else if ((c == ' ' || c == '\n') && (def != -1))
12290 break;
12292 if (def)
12293 puts("yes\n");
12294 else
12295 puts ("no\n");
12296 #ifdef HAVE_TERMIOS_H
12297 tcsetattr_stdin_TCSANOW(&termios);
12298 #endif
12299 return def;
12302 int ask (e2fsck_t ctx, const char * string, int def)
12304 if (ctx->options & E2F_OPT_NO) {
12305 printf(_("%s? no\n\n"), string);
12306 return 0;
12308 if (ctx->options & E2F_OPT_YES) {
12309 printf(_("%s? yes\n\n"), string);
12310 return 1;
12312 if (ctx->options & E2F_OPT_PREEN) {
12313 printf("%s? %s\n\n", string, def ? _("yes") : _("no"));
12314 return def;
12316 return ask_yn(string, def);
12319 void e2fsck_read_bitmaps(e2fsck_t ctx)
12321 ext2_filsys fs = ctx->fs;
12322 errcode_t retval;
12324 if (ctx->invalid_bitmaps) {
12325 bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12326 ctx->device_name);
12327 bb_error_msg_and_die(0);
12330 ehandler_operation(_("reading inode and block bitmaps"));
12331 retval = ext2fs_read_bitmaps(fs);
12332 ehandler_operation(0);
12333 if (retval) {
12334 bb_error_msg(_("while retrying to read bitmaps for %s"),
12335 ctx->device_name);
12336 bb_error_msg_and_die(0);
12340 static void e2fsck_write_bitmaps(e2fsck_t ctx)
12342 ext2_filsys fs = ctx->fs;
12343 errcode_t retval;
12345 if (ext2fs_test_bb_dirty(fs)) {
12346 ehandler_operation(_("writing block bitmaps"));
12347 retval = ext2fs_write_block_bitmap(fs);
12348 ehandler_operation(0);
12349 if (retval) {
12350 bb_error_msg(_("while retrying to write block bitmaps for %s"),
12351 ctx->device_name);
12352 bb_error_msg_and_die(0);
12356 if (ext2fs_test_ib_dirty(fs)) {
12357 ehandler_operation(_("writing inode bitmaps"));
12358 retval = ext2fs_write_inode_bitmap(fs);
12359 ehandler_operation(0);
12360 if (retval) {
12361 bb_error_msg(_("while retrying to write inode bitmaps for %s"),
12362 ctx->device_name);
12363 bb_error_msg_and_die(0);
12368 void preenhalt(e2fsck_t ctx)
12370 ext2_filsys fs = ctx->fs;
12372 if (!(ctx->options & E2F_OPT_PREEN))
12373 return;
12374 fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12375 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12376 ctx->device_name);
12377 if (fs != NULL) {
12378 fs->super->s_state |= EXT2_ERROR_FS;
12379 ext2fs_mark_super_dirty(fs);
12380 ext2fs_close(fs);
12382 exit(EXIT_UNCORRECTED);
12385 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12386 struct ext2_inode * inode, const char *proc)
12388 int retval;
12390 retval = ext2fs_read_inode(ctx->fs, ino, inode);
12391 if (retval) {
12392 bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
12393 bb_error_msg_and_die(0);
12397 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12398 struct ext2_inode * inode, int bufsize,
12399 const char *proc)
12401 int retval;
12403 retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12404 if (retval) {
12405 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12406 bb_error_msg_and_die(0);
12410 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12411 struct ext2_inode * inode, const char *proc)
12413 int retval;
12415 retval = ext2fs_write_inode(ctx->fs, ino, inode);
12416 if (retval) {
12417 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12418 bb_error_msg_and_die(0);
12422 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12423 io_manager manager)
12425 struct ext2_super_block *sb;
12426 io_channel io = NULL;
12427 void *buf = NULL;
12428 int blocksize;
12429 blk_t superblock, ret_sb = 8193;
12431 if (fs && fs->super) {
12432 ret_sb = (fs->super->s_blocks_per_group +
12433 fs->super->s_first_data_block);
12434 if (ctx) {
12435 ctx->superblock = ret_sb;
12436 ctx->blocksize = fs->blocksize;
12438 return ret_sb;
12441 if (ctx) {
12442 if (ctx->blocksize) {
12443 ret_sb = ctx->blocksize * 8;
12444 if (ctx->blocksize == 1024)
12445 ret_sb++;
12446 ctx->superblock = ret_sb;
12447 return ret_sb;
12449 ctx->superblock = ret_sb;
12450 ctx->blocksize = 1024;
12453 if (!name || !manager)
12454 goto cleanup;
12456 if (manager->open(name, 0, &io) != 0)
12457 goto cleanup;
12459 if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12460 goto cleanup;
12461 sb = (struct ext2_super_block *) buf;
12463 for (blocksize = EXT2_MIN_BLOCK_SIZE;
12464 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
12465 superblock = blocksize*8;
12466 if (blocksize == 1024)
12467 superblock++;
12468 io_channel_set_blksize(io, blocksize);
12469 if (io_channel_read_blk(io, superblock,
12470 -SUPERBLOCK_SIZE, buf))
12471 continue;
12472 #if BB_BIG_ENDIAN
12473 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12474 ext2fs_swap_super(sb);
12475 #endif
12476 if (sb->s_magic == EXT2_SUPER_MAGIC) {
12477 ret_sb = superblock;
12478 if (ctx) {
12479 ctx->superblock = superblock;
12480 ctx->blocksize = blocksize;
12482 break;
12486 cleanup:
12487 if (io)
12488 io_channel_close(io);
12489 ext2fs_free_mem(&buf);
12490 return ret_sb;
12495 * This function runs through the e2fsck passes and calls them all,
12496 * returning restart, abort, or cancel as necessary...
12498 typedef void (*pass_t)(e2fsck_t ctx);
12500 static const pass_t e2fsck_passes[] = {
12501 e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12502 e2fsck_pass5, 0 };
12504 #define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12506 static int e2fsck_run(e2fsck_t ctx)
12508 int i;
12509 pass_t e2fsck_pass;
12511 if (setjmp(ctx->abort_loc)) {
12512 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12513 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12515 ctx->flags |= E2F_FLAG_SETJMP_OK;
12517 for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12518 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12519 break;
12520 e2fsck_pass(ctx);
12521 if (ctx->progress)
12522 (void) (ctx->progress)(ctx, 0, 0, 0);
12524 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12526 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12527 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12528 return 0;
12533 * unix.c - The unix-specific code for e2fsck
12537 /* Command line options */
12538 static int swapfs;
12539 #ifdef ENABLE_SWAPFS
12540 static int normalize_swapfs;
12541 #endif
12542 static int cflag; /* check disk */
12543 static int show_version_only;
12544 static int verbose;
12546 #define P_E2(singular, plural, n) n, ((n) == 1 ? singular : plural)
12548 static void show_stats(e2fsck_t ctx)
12550 ext2_filsys fs = ctx->fs;
12551 int inodes, inodes_used, blocks, blocks_used;
12552 int dir_links;
12553 int num_files, num_links;
12554 int frag_percent;
12556 dir_links = 2 * ctx->fs_directory_count - 1;
12557 num_files = ctx->fs_total_count - dir_links;
12558 num_links = ctx->fs_links_count - dir_links;
12559 inodes = fs->super->s_inodes_count;
12560 inodes_used = (fs->super->s_inodes_count -
12561 fs->super->s_free_inodes_count);
12562 blocks = fs->super->s_blocks_count;
12563 blocks_used = (fs->super->s_blocks_count -
12564 fs->super->s_free_blocks_count);
12566 frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12567 frag_percent = (frag_percent + 5) / 10;
12569 if (!verbose) {
12570 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12571 ctx->device_name, inodes_used, inodes,
12572 frag_percent / 10, frag_percent % 10,
12573 blocks_used, blocks);
12574 return;
12576 printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12577 100 * inodes_used / inodes);
12578 printf("%8d non-contiguous inode%s (%0d.%d%%)\n",
12579 P_E2("", "s", ctx->fs_fragmented),
12580 frag_percent / 10, frag_percent % 10);
12581 printf(_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12582 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12583 printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12584 (int) ((long long) 100 * blocks_used / blocks));
12585 printf("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12586 printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12587 printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12588 printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12589 printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12590 printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12591 printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12592 printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12593 printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12594 printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12595 printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12598 static void check_mount(e2fsck_t ctx)
12600 errcode_t retval;
12601 int cont;
12603 retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12604 &ctx->mount_flags);
12605 if (retval) {
12606 bb_error_msg(_("while determining whether %s is mounted"),
12607 ctx->filesystem_name);
12608 return;
12612 * If the filesystem isn't mounted, or it's the root filesystem
12613 * and it's mounted read-only, then everything's fine.
12615 if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12616 ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12617 (ctx->mount_flags & EXT2_MF_READONLY)))
12618 return;
12620 if (ctx->options & E2F_OPT_READONLY) {
12621 printf(_("Warning! %s is mounted.\n"), ctx->filesystem_name);
12622 return;
12625 printf(_("%s is mounted. "), ctx->filesystem_name);
12626 if (!ctx->interactive)
12627 bb_error_msg_and_die(_("can't continue, aborting"));
12628 printf(_("\n\n\007\007\007\007WARNING!!! "
12629 "Running e2fsck on a mounted filesystem may cause\n"
12630 "SEVERE filesystem damage.\007\007\007\n\n"));
12631 cont = ask_yn(_("Do you really want to continue"), -1);
12632 if (!cont) {
12633 printf(_("check aborted.\n"));
12634 exit(0);
12638 static int is_on_batt(void)
12640 FILE *f;
12641 DIR *d;
12642 char tmp[80], tmp2[80], fname[80];
12643 unsigned int acflag;
12644 struct dirent* de;
12646 f = fopen_for_read("/proc/apm");
12647 if (f) {
12648 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12649 acflag = 1;
12650 fclose(f);
12651 return (acflag != 1);
12653 d = opendir("/proc/acpi/ac_adapter");
12654 if (d) {
12655 while ((de=readdir(d)) != NULL) {
12656 if (!strncmp(".", de->d_name, 1))
12657 continue;
12658 snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12659 de->d_name);
12660 f = fopen_for_read(fname);
12661 if (!f)
12662 continue;
12663 if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12664 tmp[0] = 0;
12665 fclose(f);
12666 if (strncmp(tmp, "off-line", 8) == 0) {
12667 closedir(d);
12668 return 1;
12671 closedir(d);
12673 return 0;
12677 * This routine checks to see if a filesystem can be skipped; if so,
12678 * it will exit with EXIT_OK. Under some conditions it will print a
12679 * message explaining why a check is being forced.
12681 static void check_if_skip(e2fsck_t ctx)
12683 ext2_filsys fs = ctx->fs;
12684 const char *reason = NULL;
12685 unsigned int reason_arg = 0;
12686 long next_check;
12687 int batt = is_on_batt();
12688 time_t now = time(NULL);
12690 if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12691 return;
12693 if ((fs->super->s_state & EXT2_ERROR_FS) ||
12694 !ext2fs_test_valid(fs))
12695 reason = _(" contains a file system with errors");
12696 else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12697 reason = _(" was not cleanly unmounted");
12698 else if ((fs->super->s_max_mnt_count > 0) &&
12699 (fs->super->s_mnt_count >=
12700 (unsigned) fs->super->s_max_mnt_count)) {
12701 reason = _(" has been mounted %u times without being checked");
12702 reason_arg = fs->super->s_mnt_count;
12703 if (batt && (fs->super->s_mnt_count <
12704 (unsigned) fs->super->s_max_mnt_count*2))
12705 reason = 0;
12706 } else if (!(ctx->options & E2F_OPT_PREEN) &&
12707 fs->super->s_checkinterval &&
12708 ((now - fs->super->s_lastcheck) >=
12709 fs->super->s_checkinterval)) {
12710 reason = _(" has gone %u days without being checked");
12711 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12712 if (batt && ((now - fs->super->s_lastcheck) <
12713 fs->super->s_checkinterval*2))
12714 reason = 0;
12716 if (reason) {
12717 fputs(ctx->device_name, stdout);
12718 printf(reason, reason_arg);
12719 fputs(_(", check forced.\n"), stdout);
12720 return;
12722 printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12723 fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12724 fs->super->s_inodes_count,
12725 fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12726 fs->super->s_blocks_count);
12727 next_check = 100000;
12728 if (fs->super->s_max_mnt_count > 0) {
12729 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12730 if (next_check <= 0)
12731 next_check = 1;
12733 if (fs->super->s_checkinterval &&
12734 ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12735 next_check = 1;
12736 if (next_check <= 5) {
12737 if (next_check == 1)
12738 fputs(_(" (check after next mount)"), stdout);
12739 else
12740 printf(_(" (check in %ld mounts)"), next_check);
12742 bb_putchar('\n');
12743 ext2fs_close(fs);
12744 ctx->fs = NULL;
12745 e2fsck_free_context(ctx);
12746 exit(EXIT_OK);
12750 * For completion notice
12752 struct percent_tbl {
12753 int max_pass;
12754 int table[32];
12756 static const struct percent_tbl e2fsck_tbl = {
12757 5, { 0, 70, 90, 92, 95, 100 }
12760 static char bar[128], spaces[128];
12762 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12763 int max)
12765 float percent;
12767 if (pass <= 0)
12768 return 0.0;
12769 if (pass > tbl->max_pass || max == 0)
12770 return 100.0;
12771 percent = ((float) curr) / ((float) max);
12772 return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12773 + tbl->table[pass-1]);
12776 void e2fsck_clear_progbar(e2fsck_t ctx)
12778 if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12779 return;
12781 printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12782 ctx->stop_meta);
12783 fflush(stdout);
12784 ctx->flags &= ~E2F_FLAG_PROG_BAR;
12787 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12788 unsigned int dpynum)
12790 static const char spinner[] = "\\|/-";
12791 int i;
12792 unsigned int tick;
12793 struct timeval tv;
12794 int dpywidth;
12795 int fixed_percent;
12797 if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12798 return 0;
12801 * Calculate the new progress position. If the
12802 * percentage hasn't changed, then we skip out right
12803 * away.
12805 fixed_percent = (int) ((10 * percent) + 0.5);
12806 if (ctx->progress_last_percent == fixed_percent)
12807 return 0;
12808 ctx->progress_last_percent = fixed_percent;
12811 * If we've already updated the spinner once within
12812 * the last 1/8th of a second, no point doing it
12813 * again.
12815 gettimeofday(&tv, NULL);
12816 tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12817 if ((tick == ctx->progress_last_time) &&
12818 (fixed_percent != 0) && (fixed_percent != 1000))
12819 return 0;
12820 ctx->progress_last_time = tick;
12823 * Advance the spinner, and note that the progress bar
12824 * will be on the screen
12826 ctx->progress_pos = (ctx->progress_pos+1) & 3;
12827 ctx->flags |= E2F_FLAG_PROG_BAR;
12829 dpywidth = 66 - strlen(label);
12830 dpywidth = 8 * (dpywidth / 8);
12831 if (dpynum)
12832 dpywidth -= 8;
12834 i = ((percent * dpywidth) + 50) / 100;
12835 printf("%s%s: |%s%s", ctx->start_meta, label,
12836 bar + (sizeof(bar) - (i+1)),
12837 spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12838 if (fixed_percent == 1000)
12839 bb_putchar('|');
12840 else
12841 bb_putchar(spinner[ctx->progress_pos & 3]);
12842 printf(" %4.1f%% ", percent);
12843 if (dpynum)
12844 printf("%u\r", dpynum);
12845 else
12846 fputs(" \r", stdout);
12847 fputs(ctx->stop_meta, stdout);
12849 if (fixed_percent == 1000)
12850 e2fsck_clear_progbar(ctx);
12851 fflush(stdout);
12853 return 0;
12856 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12857 unsigned long cur, unsigned long max)
12859 char buf[80];
12860 float percent;
12862 if (pass == 0)
12863 return 0;
12865 if (ctx->progress_fd) {
12866 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
12867 xwrite_str(ctx->progress_fd, buf);
12868 } else {
12869 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12870 e2fsck_simple_progress(ctx, ctx->device_name,
12871 percent, 0);
12873 return 0;
12876 static void reserve_stdio_fds(void)
12878 int fd;
12880 while (1) {
12881 fd = open(bb_dev_null, O_RDWR);
12882 if (fd > 2)
12883 break;
12884 if (fd < 0) {
12885 fprintf(stderr, _("ERROR: Cannot open "
12886 "/dev/null (%s)\n"),
12887 strerror(errno));
12888 break;
12891 close(fd);
12894 static void signal_progress_on(int sig FSCK_ATTR((unused)))
12896 e2fsck_t ctx = e2fsck_global_ctx;
12898 if (!ctx)
12899 return;
12901 ctx->progress = e2fsck_update_progress;
12902 ctx->progress_fd = 0;
12905 static void signal_progress_off(int sig FSCK_ATTR((unused)))
12907 e2fsck_t ctx = e2fsck_global_ctx;
12909 if (!ctx)
12910 return;
12912 e2fsck_clear_progbar(ctx);
12913 ctx->progress = 0;
12916 static void signal_cancel(int sig FSCK_ATTR((unused)))
12918 e2fsck_t ctx = e2fsck_global_ctx;
12920 if (!ctx)
12921 exit(FSCK_CANCELED);
12923 ctx->flags |= E2F_FLAG_CANCEL;
12926 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12928 char *buf, *token, *next, *p, *arg;
12929 int ea_ver;
12930 int extended_usage = 0;
12932 buf = string_copy(opts, 0);
12933 for (token = buf; token && *token; token = next) {
12934 p = strchr(token, ',');
12935 next = 0;
12936 if (p) {
12937 *p = 0;
12938 next = p+1;
12940 arg = strchr(token, '=');
12941 if (arg) {
12942 *arg = 0;
12943 arg++;
12945 if (strcmp(token, "ea_ver") == 0) {
12946 if (!arg) {
12947 extended_usage++;
12948 continue;
12950 ea_ver = strtoul(arg, &p, 0);
12951 if (*p ||
12952 ((ea_ver != 1) && (ea_ver != 2))) {
12953 fprintf(stderr,
12954 _("Invalid EA version.\n"));
12955 extended_usage++;
12956 continue;
12958 ctx->ext_attr_ver = ea_ver;
12959 } else {
12960 fprintf(stderr, _("Unknown extended option: %s\n"),
12961 token);
12962 extended_usage++;
12965 if (extended_usage) {
12966 bb_error_msg_and_die(
12967 "Extended options are separated by commas, "
12968 "and may take an argument which\n"
12969 "is set off by an equals ('=') sign. "
12970 "Valid extended options are:\n"
12971 "\tea_ver=<ea_version (1 or 2)>\n\n");
12976 static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
12978 int flush = 0;
12979 int c, fd;
12980 e2fsck_t ctx;
12981 errcode_t retval;
12982 struct sigaction sa;
12983 char *extended_opts = NULL;
12985 retval = e2fsck_allocate_context(&ctx);
12986 if (retval)
12987 return retval;
12989 *ret_ctx = ctx;
12991 setvbuf(stdout, NULL, _IONBF, BUFSIZ);
12992 setvbuf(stderr, NULL, _IONBF, BUFSIZ);
12993 if (isatty(0) && isatty(1)) {
12994 ctx->interactive = 1;
12995 } else {
12996 ctx->start_meta[0] = '\001';
12997 ctx->stop_meta[0] = '\002';
12999 memset(bar, '=', sizeof(bar)-1);
13000 memset(spaces, ' ', sizeof(spaces)-1);
13002 if (argc && *argv)
13003 ctx->program_name = *argv;
13004 else
13005 ctx->program_name = "e2fsck";
13006 while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
13007 switch (c) {
13008 case 'C':
13009 ctx->progress = e2fsck_update_progress;
13010 ctx->progress_fd = atoi(optarg);
13011 if (!ctx->progress_fd)
13012 break;
13013 /* Validate the file descriptor to avoid disasters */
13014 fd = dup(ctx->progress_fd);
13015 if (fd < 0) {
13016 fprintf(stderr,
13017 _("Error validating file descriptor %d: %s\n"),
13018 ctx->progress_fd,
13019 error_message(errno));
13020 bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13021 } else
13022 close(fd);
13023 break;
13024 case 'D':
13025 ctx->options |= E2F_OPT_COMPRESS_DIRS;
13026 break;
13027 case 'E':
13028 extended_opts = optarg;
13029 break;
13030 case 'p':
13031 case 'a':
13032 if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13033 conflict_opt:
13034 bb_error_msg_and_die(_("only one the options -p/-a, -n or -y may be specified"));
13036 ctx->options |= E2F_OPT_PREEN;
13037 break;
13038 case 'n':
13039 if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13040 goto conflict_opt;
13041 ctx->options |= E2F_OPT_NO;
13042 break;
13043 case 'y':
13044 if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13045 goto conflict_opt;
13046 ctx->options |= E2F_OPT_YES;
13047 break;
13048 case 't':
13049 /* FIXME - This needs to go away in a future path - will change binary */
13050 fprintf(stderr, _("The -t option is not "
13051 "supported on this version of e2fsck.\n"));
13052 break;
13053 case 'c':
13054 if (cflag++)
13055 ctx->options |= E2F_OPT_WRITECHECK;
13056 ctx->options |= E2F_OPT_CHECKBLOCKS;
13057 break;
13058 case 'r':
13059 /* What we do by default, anyway! */
13060 break;
13061 case 'b':
13062 ctx->use_superblock = atoi(optarg);
13063 ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13064 break;
13065 case 'B':
13066 ctx->blocksize = atoi(optarg);
13067 break;
13068 case 'I':
13069 ctx->inode_buffer_blocks = atoi(optarg);
13070 break;
13071 case 'j':
13072 ctx->journal_name = string_copy(optarg, 0);
13073 break;
13074 case 'P':
13075 ctx->process_inode_size = atoi(optarg);
13076 break;
13077 case 'd':
13078 ctx->options |= E2F_OPT_DEBUG;
13079 break;
13080 case 'f':
13081 ctx->options |= E2F_OPT_FORCE;
13082 break;
13083 case 'F':
13084 flush = 1;
13085 break;
13086 case 'v':
13087 verbose = 1;
13088 break;
13089 case 'V':
13090 show_version_only = 1;
13091 break;
13092 case 'N':
13093 ctx->device_name = optarg;
13094 break;
13095 #ifdef ENABLE_SWAPFS
13096 case 's':
13097 normalize_swapfs = 1;
13098 case 'S':
13099 swapfs = 1;
13100 break;
13101 #else
13102 case 's':
13103 case 'S':
13104 fprintf(stderr, _("Byte-swapping filesystems "
13105 "not compiled in this version "
13106 "of e2fsck\n"));
13107 exit(1);
13108 #endif
13109 default:
13110 bb_show_usage();
13112 if (show_version_only)
13113 return 0;
13114 if (optind != argc - 1)
13115 bb_show_usage();
13116 if ((ctx->options & E2F_OPT_NO) &&
13117 !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13118 ctx->options |= E2F_OPT_READONLY;
13119 ctx->io_options = strchr(argv[optind], '?');
13120 if (ctx->io_options)
13121 *ctx->io_options++ = 0;
13122 ctx->filesystem_name = argv[optind];
13123 if (resolve_mount_spec(&ctx->filesystem_name) < 0 ||
13124 !ctx->filesystem_name) {
13125 bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
13126 bb_error_msg_and_die(0);
13128 if (extended_opts)
13129 parse_extended_opts(ctx, extended_opts);
13131 if (flush) {
13132 fd = open(ctx->filesystem_name, O_RDONLY, 0);
13133 if (fd < 0) {
13134 bb_error_msg(_("while opening %s for flushing"),
13135 ctx->filesystem_name);
13136 bb_error_msg_and_die(0);
13138 if ((retval = ext2fs_sync_device(fd, 1))) {
13139 bb_error_msg(_("while trying to flush %s"),
13140 ctx->filesystem_name);
13141 bb_error_msg_and_die(0);
13143 close(fd);
13145 #ifdef ENABLE_SWAPFS
13146 if (swapfs && cflag) {
13147 fprintf(stderr, _("Incompatible options not "
13148 "allowed when byte-swapping.\n"));
13149 exit(EXIT_USAGE);
13151 #endif
13153 * Set up signal action
13155 memset(&sa, 0, sizeof(struct sigaction));
13156 sa.sa_handler = signal_cancel;
13157 sigaction(SIGINT, &sa, 0);
13158 sigaction(SIGTERM, &sa, 0);
13159 #ifdef SA_RESTART
13160 sa.sa_flags = SA_RESTART;
13161 #endif
13162 e2fsck_global_ctx = ctx;
13163 sa.sa_handler = signal_progress_on;
13164 sigaction(SIGUSR1, &sa, 0);
13165 sa.sa_handler = signal_progress_off;
13166 sigaction(SIGUSR2, &sa, 0);
13168 /* Update our PATH to include /sbin if we need to run badblocks */
13169 if (cflag)
13170 e2fs_set_sbin_path();
13171 return 0;
13174 static const char my_ver_string[] = E2FSPROGS_VERSION;
13175 static const char my_ver_date[] = E2FSPROGS_DATE;
13177 int e2fsck_main (int argc, char **argv);
13178 int e2fsck_main (int argc, char **argv)
13180 errcode_t retval;
13181 int exit_value = EXIT_OK;
13182 ext2_filsys fs = 0;
13183 io_manager io_ptr;
13184 struct ext2_super_block *sb;
13185 const char *lib_ver_date;
13186 int my_ver, lib_ver;
13187 e2fsck_t ctx;
13188 struct problem_context pctx;
13189 int flags, run_result;
13191 clear_problem_context(&pctx);
13193 my_ver = ext2fs_parse_version_string(my_ver_string);
13194 lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13195 if (my_ver > lib_ver) {
13196 fprintf( stderr, _("Error: ext2fs library version "
13197 "out of date!\n"));
13198 show_version_only++;
13201 retval = PRS(argc, argv, &ctx);
13202 if (retval) {
13203 bb_error_msg(_("while trying to initialize program"));
13204 exit(EXIT_ERROR);
13206 reserve_stdio_fds();
13208 if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13209 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13210 my_ver_date);
13212 if (show_version_only) {
13213 fprintf(stderr, _("\tUsing %s, %s\n"),
13214 error_message(EXT2_ET_BASE), lib_ver_date);
13215 exit(EXIT_OK);
13218 check_mount(ctx);
13220 if (!(ctx->options & E2F_OPT_PREEN) &&
13221 !(ctx->options & E2F_OPT_NO) &&
13222 !(ctx->options & E2F_OPT_YES)) {
13223 if (!ctx->interactive)
13224 bb_error_msg_and_die(_("need terminal for interactive repairs"));
13226 ctx->superblock = ctx->use_superblock;
13227 restart:
13228 #ifdef CONFIG_TESTIO_DEBUG
13229 io_ptr = test_io_manager;
13230 test_io_backing_manager = unix_io_manager;
13231 #else
13232 io_ptr = unix_io_manager;
13233 #endif
13234 flags = 0;
13235 if ((ctx->options & E2F_OPT_READONLY) == 0)
13236 flags |= EXT2_FLAG_RW;
13238 if (ctx->superblock && ctx->blocksize) {
13239 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13240 flags, ctx->superblock, ctx->blocksize,
13241 io_ptr, &fs);
13242 } else if (ctx->superblock) {
13243 int blocksize;
13244 for (blocksize = EXT2_MIN_BLOCK_SIZE;
13245 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13246 retval = ext2fs_open2(ctx->filesystem_name,
13247 ctx->io_options, flags,
13248 ctx->superblock, blocksize,
13249 io_ptr, &fs);
13250 if (!retval)
13251 break;
13253 } else
13254 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13255 flags, 0, 0, io_ptr, &fs);
13256 if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13257 !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13258 ((retval == EXT2_ET_BAD_MAGIC) ||
13259 ((retval == 0) && ext2fs_check_desc(fs)))) {
13260 if (!fs || (fs->group_desc_count > 1)) {
13261 printf(_("%s trying backup blocks...\n"),
13262 retval ? _("Couldn't find ext2 superblock,") :
13263 _("Group descriptors look bad..."));
13264 get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13265 if (fs)
13266 ext2fs_close(fs);
13267 goto restart;
13270 if (retval) {
13271 bb_error_msg(_("while trying to open %s"),
13272 ctx->filesystem_name);
13273 if (retval == EXT2_ET_REV_TOO_HIGH) {
13274 printf(_("The filesystem revision is apparently "
13275 "too high for this version of e2fsck.\n"
13276 "(Or the filesystem superblock "
13277 "is corrupt)\n\n"));
13278 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13279 } else if (retval == EXT2_ET_SHORT_READ)
13280 printf(_("Could this be a zero-length partition?\n"));
13281 else if ((retval == EPERM) || (retval == EACCES))
13282 printf(_("You must have %s access to the "
13283 "filesystem or be root\n"),
13284 (ctx->options & E2F_OPT_READONLY) ?
13285 "r/o" : "r/w");
13286 else if (retval == ENXIO)
13287 printf(_("Possibly non-existent or swap device?\n"));
13288 #ifdef EROFS
13289 else if (retval == EROFS)
13290 printf(_("Disk write-protected; use the -n option "
13291 "to do a read-only\n"
13292 "check of the device.\n"));
13293 #endif
13294 else
13295 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13296 bb_error_msg_and_die(0);
13298 ctx->fs = fs;
13299 fs->priv_data = ctx;
13300 sb = fs->super;
13301 if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13302 bb_error_msg(_("while trying to open %s"),
13303 ctx->filesystem_name);
13304 get_newer:
13305 bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13309 * Set the device name, which is used whenever we print error
13310 * or informational messages to the user.
13312 if (ctx->device_name == 0 &&
13313 (sb->s_volume_name[0] != 0)) {
13314 ctx->device_name = string_copy(sb->s_volume_name,
13315 sizeof(sb->s_volume_name));
13317 if (ctx->device_name == 0)
13318 ctx->device_name = ctx->filesystem_name;
13321 * Make sure the ext3 superblock fields are consistent.
13323 retval = e2fsck_check_ext3_journal(ctx);
13324 if (retval) {
13325 bb_error_msg(_("while checking ext3 journal for %s"),
13326 ctx->device_name);
13327 bb_error_msg_and_die(0);
13331 * Check to see if we need to do ext3-style recovery. If so,
13332 * do it, and then restart the fsck.
13334 if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13335 if (ctx->options & E2F_OPT_READONLY) {
13336 printf(_("Warning: skipping journal recovery "
13337 "because doing a read-only filesystem "
13338 "check.\n"));
13339 io_channel_flush(ctx->fs->io);
13340 } else {
13341 if (ctx->flags & E2F_FLAG_RESTARTED) {
13343 * Whoops, we attempted to run the
13344 * journal twice. This should never
13345 * happen, unless the hardware or
13346 * device driver is being bogus.
13348 bb_error_msg(_("can't set superblock flags on %s"), ctx->device_name);
13349 bb_error_msg_and_die(0);
13351 retval = e2fsck_run_ext3_journal(ctx);
13352 if (retval) {
13353 bb_error_msg(_("while recovering ext3 journal of %s"),
13354 ctx->device_name);
13355 bb_error_msg_and_die(0);
13357 ext2fs_close(ctx->fs);
13358 ctx->fs = 0;
13359 ctx->flags |= E2F_FLAG_RESTARTED;
13360 goto restart;
13365 * Check for compatibility with the feature sets. We need to
13366 * be more stringent than ext2fs_open().
13368 if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13369 (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13370 bb_error_msg("(%s)", ctx->device_name);
13371 goto get_newer;
13373 if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13374 bb_error_msg("(%s)", ctx->device_name);
13375 goto get_newer;
13377 #ifdef ENABLE_COMPRESSION
13378 /* FIXME - do we support this at all? */
13379 if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
13380 bb_error_msg(_("warning: compression support is experimental"));
13381 #endif
13382 #ifndef ENABLE_HTREE
13383 if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13384 bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13385 "but filesystem %s has HTREE directories."),
13386 ctx->device_name);
13387 goto get_newer;
13389 #endif
13392 * If the user specified a specific superblock, presumably the
13393 * master superblock has been trashed. So we mark the
13394 * superblock as dirty, so it can be written out.
13396 if (ctx->superblock &&
13397 !(ctx->options & E2F_OPT_READONLY))
13398 ext2fs_mark_super_dirty(fs);
13401 * We only update the master superblock because (a) paranoia;
13402 * we don't want to corrupt the backup superblocks, and (b) we
13403 * don't need to update the mount count and last checked
13404 * fields in the backup superblock (the kernel doesn't
13405 * update the backup superblocks anyway).
13407 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13409 ehandler_init(fs->io);
13411 if (ctx->superblock)
13412 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13413 ext2fs_mark_valid(fs);
13414 check_super_block(ctx);
13415 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13416 bb_error_msg_and_die(0);
13417 check_if_skip(ctx);
13418 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13419 bb_error_msg_and_die(0);
13420 #ifdef ENABLE_SWAPFS
13422 #ifdef WORDS_BIGENDIAN
13423 #define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13424 #else
13425 #define NATIVE_FLAG 0
13426 #endif
13429 if (normalize_swapfs) {
13430 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13431 fprintf(stderr, _("%s: Filesystem byte order "
13432 "already normalized.\n"), ctx->device_name);
13433 bb_error_msg_and_die(0);
13436 if (swapfs) {
13437 swap_filesys(ctx);
13438 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13439 bb_error_msg_and_die(0);
13441 #endif
13444 * Mark the system as valid, 'til proven otherwise
13446 ext2fs_mark_valid(fs);
13448 retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13449 if (retval) {
13450 bb_error_msg(_("while reading bad blocks inode"));
13451 preenhalt(ctx);
13452 printf(_("This doesn't bode well,"
13453 " but we'll try to go on...\n"));
13456 run_result = e2fsck_run(ctx);
13457 e2fsck_clear_progbar(ctx);
13458 if (run_result == E2F_FLAG_RESTART) {
13459 printf(_("Restarting e2fsck from the beginning...\n"));
13460 retval = e2fsck_reset_context(ctx);
13461 if (retval) {
13462 bb_error_msg(_("while resetting context"));
13463 bb_error_msg_and_die(0);
13465 ext2fs_close(fs);
13466 goto restart;
13468 if (run_result & E2F_FLAG_CANCEL) {
13469 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13470 ctx->device_name : ctx->filesystem_name);
13471 exit_value |= FSCK_CANCELED;
13473 if (run_result & E2F_FLAG_ABORT)
13474 bb_error_msg_and_die(_("aborted"));
13476 /* Cleanup */
13477 if (ext2fs_test_changed(fs)) {
13478 exit_value |= EXIT_NONDESTRUCT;
13479 if (!(ctx->options & E2F_OPT_PREEN))
13480 printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13481 ctx->device_name);
13482 if (ctx->mount_flags & EXT2_MF_ISROOT) {
13483 printf(_("%s: ***** REBOOT LINUX *****\n"),
13484 ctx->device_name);
13485 exit_value |= EXIT_DESTRUCT;
13488 if (!ext2fs_test_valid(fs)) {
13489 printf(_("\n%s: ********** WARNING: Filesystem still has "
13490 "errors **********\n\n"), ctx->device_name);
13491 exit_value |= EXIT_UNCORRECTED;
13492 exit_value &= ~EXIT_NONDESTRUCT;
13494 if (exit_value & FSCK_CANCELED)
13495 exit_value &= ~EXIT_NONDESTRUCT;
13496 else {
13497 show_stats(ctx);
13498 if (!(ctx->options & E2F_OPT_READONLY)) {
13499 if (ext2fs_test_valid(fs)) {
13500 if (!(sb->s_state & EXT2_VALID_FS))
13501 exit_value |= EXIT_NONDESTRUCT;
13502 sb->s_state = EXT2_VALID_FS;
13503 } else
13504 sb->s_state &= ~EXT2_VALID_FS;
13505 sb->s_mnt_count = 0;
13506 sb->s_lastcheck = time(NULL);
13507 ext2fs_mark_super_dirty(fs);
13511 e2fsck_write_bitmaps(ctx);
13513 ext2fs_close(fs);
13514 ctx->fs = NULL;
13515 free(ctx->filesystem_name);
13516 free(ctx->journal_name);
13517 e2fsck_free_context(ctx);
13519 return exit_value;