Busybox 1.20.2 update
[tomato.git] / release / src / router / busybox / e2fsprogs / e2fsck.c
blobdb9f8ce965cc2f15aa469a9249c4f904e4050512
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"
51 //usage:#define fsck_ext2_trivial_usage NOUSAGE_STR
52 //usage:#define fsck_ext2_full_usage ""
54 //usage:#define fsck_ext3_trivial_usage NOUSAGE_STR
55 //usage:#define fsck_ext3_full_usage ""
57 #include "e2fsck.h" /*Put all of our defines here to clean things up*/
59 #define _(x) x
60 #define N_(x) x
63 * Procedure declarations
66 static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
68 /* pass1.c */
69 static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int fl_bool);
71 /* pass2.c */
72 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
73 ext2_ino_t ino, char *buf);
75 /* pass3.c */
76 static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
77 static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
78 int num, int gauranteed_size);
79 static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
80 static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
81 int adj);
83 /* rehash.c */
84 static void e2fsck_rehash_directories(e2fsck_t ctx);
86 /* util.c */
87 static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
88 const char *description);
89 static int ask(e2fsck_t ctx, const char * string, int def);
90 static void e2fsck_read_bitmaps(e2fsck_t ctx);
91 static void preenhalt(e2fsck_t ctx);
92 static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
93 struct ext2_inode * inode, const char * proc);
94 static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
95 struct ext2_inode * inode, const char * proc);
96 static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
97 const char *name, io_manager manager);
99 /* unix.c */
100 static void e2fsck_clear_progbar(e2fsck_t ctx);
101 static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
102 float percent, unsigned int dpynum);
106 * problem.h --- e2fsck problem error codes
109 typedef __u32 problem_t;
111 struct problem_context {
112 errcode_t errcode;
113 ext2_ino_t ino, ino2, dir;
114 struct ext2_inode *inode;
115 struct ext2_dir_entry *dirent;
116 blk_t blk, blk2;
117 e2_blkcnt_t blkcount;
118 int group;
119 __u64 num;
120 const char *str;
125 * Function declarations
127 static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
128 static int end_problem_latch(e2fsck_t ctx, int mask);
129 static int set_latch_flags(int mask, int setflags, int clearflags);
130 static void clear_problem_context(struct problem_context *ctx);
133 * Dictionary Abstract Data Type
134 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
136 * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
137 * kazlib_1_20
140 #ifndef DICT_H
141 #define DICT_H
144 * Blurb for inclusion into C++ translation units
147 typedef unsigned long dictcount_t;
148 #define DICTCOUNT_T_MAX ULONG_MAX
151 * The dictionary is implemented as a red-black tree
154 typedef enum { dnode_red, dnode_black } dnode_color_t;
156 typedef struct dnode_t {
157 struct dnode_t *dict_left;
158 struct dnode_t *dict_right;
159 struct dnode_t *dict_parent;
160 dnode_color_t dict_color;
161 const void *dict_key;
162 void *dict_data;
163 } dnode_t;
165 typedef int (*dict_comp_t)(const void *, const void *);
166 typedef void (*dnode_free_t)(dnode_t *);
168 typedef struct dict_t {
169 dnode_t dict_nilnode;
170 dictcount_t dict_nodecount;
171 dictcount_t dict_maxcount;
172 dict_comp_t dict_compare;
173 dnode_free_t dict_freenode;
174 int dict_dupes;
175 } dict_t;
177 typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
179 typedef struct dict_load_t {
180 dict_t *dict_dictptr;
181 dnode_t dict_nilnode;
182 } dict_load_t;
184 #define dict_count(D) ((D)->dict_nodecount)
185 #define dnode_get(N) ((N)->dict_data)
186 #define dnode_getkey(N) ((N)->dict_key)
188 #endif
191 * Compatibility header file for e2fsck which should be included
192 * instead of linux/jfs.h
194 * Copyright (C) 2000 Stephen C. Tweedie
198 * Pull in the definition of the e2fsck context structure
201 struct buffer_head {
202 char b_data[8192];
203 e2fsck_t b_ctx;
204 io_channel b_io;
205 int b_size;
206 blk_t b_blocknr;
207 int b_dirty;
208 int b_uptodate;
209 int b_err;
213 #define K_DEV_FS 1
214 #define K_DEV_JOURNAL 2
216 #define lock_buffer(bh) do {} while (0)
217 #define unlock_buffer(bh) do {} while (0)
218 #define buffer_req(bh) 1
219 #define do_readahead(journal, start) do {} while (0)
221 static e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
223 typedef struct {
224 int object_length;
225 } kmem_cache_t;
227 #define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
230 * We use the standard libext2fs portability tricks for inline
231 * functions.
234 static kmem_cache_t * do_cache_create(int len)
236 kmem_cache_t *new_cache;
238 new_cache = xmalloc(sizeof(*new_cache));
239 new_cache->object_length = len;
240 return new_cache;
243 static void do_cache_destroy(kmem_cache_t *cache)
245 free(cache);
250 * Dictionary Abstract Data Type
255 * These macros provide short convenient names for structure members,
256 * which are embellished with dict_ prefixes so that they are
257 * properly confined to the documented namespace. It's legal for a
258 * program which uses dict to define, for instance, a macro called ``parent''.
259 * Such a macro would interfere with the dnode_t struct definition.
260 * In general, highly portable and reusable C modules which expose their
261 * structures need to confine structure member names to well-defined spaces.
262 * The resulting identifiers aren't necessarily convenient to use, nor
263 * readable, in the implementation, however!
266 #define left dict_left
267 #define right dict_right
268 #define parent dict_parent
269 #define color dict_color
270 #define key dict_key
271 #define data dict_data
273 #define nilnode dict_nilnode
274 #define maxcount dict_maxcount
275 #define compare dict_compare
276 #define dupes dict_dupes
278 #define dict_root(D) ((D)->nilnode.left)
279 #define dict_nil(D) (&(D)->nilnode)
281 static void dnode_free(dnode_t *node);
284 * Perform a ``left rotation'' adjustment on the tree. The given node P and
285 * its right child C are rearranged so that the P instead becomes the left
286 * child of C. The left subtree of C is inherited as the new right subtree
287 * for P. The ordering of the keys within the tree is thus preserved.
290 static void rotate_left(dnode_t *upper)
292 dnode_t *lower, *lowleft, *upparent;
294 lower = upper->right;
295 upper->right = lowleft = lower->left;
296 lowleft->parent = upper;
298 lower->parent = upparent = upper->parent;
300 /* don't need to check for root node here because root->parent is
301 the sentinel nil node, and root->parent->left points back to root */
303 if (upper == upparent->left) {
304 upparent->left = lower;
305 } else {
306 assert (upper == upparent->right);
307 upparent->right = lower;
310 lower->left = upper;
311 upper->parent = lower;
315 * This operation is the ``mirror'' image of rotate_left. It is
316 * the same procedure, but with left and right interchanged.
319 static void rotate_right(dnode_t *upper)
321 dnode_t *lower, *lowright, *upparent;
323 lower = upper->left;
324 upper->left = lowright = lower->right;
325 lowright->parent = upper;
327 lower->parent = upparent = upper->parent;
329 if (upper == upparent->right) {
330 upparent->right = lower;
331 } else {
332 assert (upper == upparent->left);
333 upparent->left = lower;
336 lower->right = upper;
337 upper->parent = lower;
341 * Do a postorder traversal of the tree rooted at the specified
342 * node and free everything under it. Used by dict_free().
345 static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
347 if (node == nil)
348 return;
349 free_nodes(dict, node->left, nil);
350 free_nodes(dict, node->right, nil);
351 dict->dict_freenode(node);
355 * Verify that the tree contains the given node. This is done by
356 * traversing all of the nodes and comparing their pointers to the
357 * given pointer. Returns 1 if the node is found, otherwise
358 * returns zero. It is intended for debugging purposes.
361 static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
363 if (root != nil) {
364 return root == node
365 || verify_dict_has_node(nil, root->left, node)
366 || verify_dict_has_node(nil, root->right, node);
368 return 0;
373 * Select a different set of node allocator routines.
376 static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
378 assert(dict_count(dict) == 0);
379 dict->dict_freenode = fr;
383 * Free all the nodes in the dictionary by using the dictionary's
384 * installed free routine. The dictionary is emptied.
387 static void dict_free_nodes(dict_t *dict)
389 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
390 free_nodes(dict, root, nil);
391 dict->dict_nodecount = 0;
392 dict->nilnode.left = &dict->nilnode;
393 dict->nilnode.right = &dict->nilnode;
397 * Initialize a user-supplied dictionary object.
400 static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
402 dict->compare = comp;
403 dict->dict_freenode = dnode_free;
404 dict->dict_nodecount = 0;
405 dict->maxcount = maxcount;
406 dict->nilnode.left = &dict->nilnode;
407 dict->nilnode.right = &dict->nilnode;
408 dict->nilnode.parent = &dict->nilnode;
409 dict->nilnode.color = dnode_black;
410 dict->dupes = 0;
411 return dict;
415 * Locate a node in the dictionary having the given key.
416 * If the node is not found, a null a pointer is returned (rather than
417 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
418 * located node is returned.
421 static dnode_t *dict_lookup(dict_t *dict, const void *key)
423 dnode_t *root = dict_root(dict);
424 dnode_t *nil = dict_nil(dict);
425 dnode_t *saved;
426 int result;
428 /* simple binary search adapted for trees that contain duplicate keys */
430 while (root != nil) {
431 result = dict->compare(key, root->key);
432 if (result < 0)
433 root = root->left;
434 else if (result > 0)
435 root = root->right;
436 else {
437 if (!dict->dupes) { /* no duplicates, return match */
438 return root;
439 } else { /* could be dupes, find leftmost one */
440 do {
441 saved = root;
442 root = root->left;
443 while (root != nil && dict->compare(key, root->key))
444 root = root->right;
445 } while (root != nil);
446 return saved;
451 return NULL;
455 * Insert a node into the dictionary. The node should have been
456 * initialized with a data field. All other fields are ignored.
457 * The behavior is undefined if the user attempts to insert into
458 * a dictionary that is already full (for which the dict_isfull()
459 * function returns true).
462 static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
464 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
465 dnode_t *parent = nil, *uncle, *grandpa;
466 int result = -1;
468 node->key = key;
470 /* basic binary tree insert */
472 while (where != nil) {
473 parent = where;
474 result = dict->compare(key, where->key);
475 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
476 assert(dict->dupes || result != 0);
477 if (result < 0)
478 where = where->left;
479 else
480 where = where->right;
483 assert(where == nil);
485 if (result < 0)
486 parent->left = node;
487 else
488 parent->right = node;
490 node->parent = parent;
491 node->left = nil;
492 node->right = nil;
494 dict->dict_nodecount++;
496 /* red black adjustments */
498 node->color = dnode_red;
500 while (parent->color == dnode_red) {
501 grandpa = parent->parent;
502 if (parent == grandpa->left) {
503 uncle = grandpa->right;
504 if (uncle->color == dnode_red) { /* red parent, red uncle */
505 parent->color = dnode_black;
506 uncle->color = dnode_black;
507 grandpa->color = dnode_red;
508 node = grandpa;
509 parent = grandpa->parent;
510 } else { /* red parent, black uncle */
511 if (node == parent->right) {
512 rotate_left(parent);
513 parent = node;
514 assert (grandpa == parent->parent);
515 /* rotation between parent and child preserves grandpa */
517 parent->color = dnode_black;
518 grandpa->color = dnode_red;
519 rotate_right(grandpa);
520 break;
522 } else { /* symmetric cases: parent == parent->parent->right */
523 uncle = grandpa->left;
524 if (uncle->color == dnode_red) {
525 parent->color = dnode_black;
526 uncle->color = dnode_black;
527 grandpa->color = dnode_red;
528 node = grandpa;
529 parent = grandpa->parent;
530 } else {
531 if (node == parent->left) {
532 rotate_right(parent);
533 parent = node;
534 assert (grandpa == parent->parent);
536 parent->color = dnode_black;
537 grandpa->color = dnode_red;
538 rotate_left(grandpa);
539 break;
544 dict_root(dict)->color = dnode_black;
548 * Allocate a node using the dictionary's allocator routine, give it
549 * the data item.
552 static dnode_t *dnode_init(dnode_t *dnode, void *data)
554 dnode->data = data;
555 dnode->parent = NULL;
556 dnode->left = NULL;
557 dnode->right = NULL;
558 return dnode;
561 static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
563 dnode_t *node = xmalloc(sizeof(dnode_t));
565 dnode_init(node, data);
566 dict_insert(dict, node, key);
567 return 1;
571 * Return the node with the lowest (leftmost) key. If the dictionary is empty
572 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
575 static dnode_t *dict_first(dict_t *dict)
577 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
579 if (root != nil)
580 while ((left = root->left) != nil)
581 root = left;
583 return (root == nil) ? NULL : root;
587 * Return the given node's successor node---the node which has the
588 * next key in the left to right ordering. If the node has
589 * no successor, a null pointer is returned rather than a pointer to
590 * the nil node.
593 static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
595 dnode_t *nil = dict_nil(dict), *parent, *left;
597 if (curr->right != nil) {
598 curr = curr->right;
599 while ((left = curr->left) != nil)
600 curr = left;
601 return curr;
604 parent = curr->parent;
606 while (parent != nil && curr == parent->right) {
607 curr = parent;
608 parent = curr->parent;
611 return (parent == nil) ? NULL : parent;
615 static void dnode_free(dnode_t *node)
617 free(node);
621 #undef left
622 #undef right
623 #undef parent
624 #undef color
625 #undef key
626 #undef data
628 #undef nilnode
629 #undef maxcount
630 #undef compare
631 #undef dupes
635 * dirinfo.c --- maintains the directory information table for e2fsck.
639 * This subroutine is called during pass1 to create a directory info
640 * entry. During pass1, the passed-in parent is 0; it will get filled
641 * in during pass2.
643 static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
645 struct dir_info *dir;
646 int i, j;
647 ext2_ino_t num_dirs;
648 errcode_t retval;
649 unsigned long old_size;
651 if (!ctx->dir_info) {
652 ctx->dir_info_count = 0;
653 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
654 if (retval)
655 num_dirs = 1024; /* Guess */
656 ctx->dir_info_size = num_dirs + 10;
657 ctx->dir_info = (struct dir_info *)
658 e2fsck_allocate_memory(ctx, ctx->dir_info_size
659 * sizeof (struct dir_info),
660 "directory map");
663 if (ctx->dir_info_count >= ctx->dir_info_size) {
664 old_size = ctx->dir_info_size * sizeof(struct dir_info);
665 ctx->dir_info_size += 10;
666 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
667 sizeof(struct dir_info),
668 &ctx->dir_info);
669 if (retval) {
670 ctx->dir_info_size -= 10;
671 return;
676 * Normally, add_dir_info is called with each inode in
677 * sequential order; but once in a while (like when pass 3
678 * needs to recreate the root directory or lost+found
679 * directory) it is called out of order. In those cases, we
680 * need to move the dir_info entries down to make room, since
681 * the dir_info array needs to be sorted by inode number for
682 * get_dir_info()'s sake.
684 if (ctx->dir_info_count &&
685 ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
686 for (i = ctx->dir_info_count-1; i > 0; i--)
687 if (ctx->dir_info[i-1].ino < ino)
688 break;
689 dir = &ctx->dir_info[i];
690 if (dir->ino != ino)
691 for (j = ctx->dir_info_count++; j > i; j--)
692 ctx->dir_info[j] = ctx->dir_info[j-1];
693 } else
694 dir = &ctx->dir_info[ctx->dir_info_count++];
696 dir->ino = ino;
697 dir->dotdot = parent;
698 dir->parent = parent;
702 * get_dir_info() --- given an inode number, try to find the directory
703 * information entry for it.
705 static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
707 int low, high, mid;
709 low = 0;
710 high = ctx->dir_info_count-1;
711 if (!ctx->dir_info)
712 return 0;
713 if (ino == ctx->dir_info[low].ino)
714 return &ctx->dir_info[low];
715 if (ino == ctx->dir_info[high].ino)
716 return &ctx->dir_info[high];
718 while (low < high) {
719 mid = (low+high)/2;
720 if (mid == low || mid == high)
721 break;
722 if (ino == ctx->dir_info[mid].ino)
723 return &ctx->dir_info[mid];
724 if (ino < ctx->dir_info[mid].ino)
725 high = mid;
726 else
727 low = mid;
729 return 0;
733 * Free the dir_info structure when it isn't needed any more.
735 static void e2fsck_free_dir_info(e2fsck_t ctx)
737 ext2fs_free_mem(&ctx->dir_info);
738 ctx->dir_info_size = 0;
739 ctx->dir_info_count = 0;
743 * Return the count of number of directories in the dir_info structure
745 static int e2fsck_get_num_dirinfo(e2fsck_t ctx)
747 return ctx->dir_info_count;
751 * A simple interator function
753 static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
755 if (*control >= ctx->dir_info_count)
756 return 0;
758 return ctx->dir_info + (*control)++;
762 * dirinfo.c --- maintains the directory information table for e2fsck.
766 #ifdef ENABLE_HTREE
769 * This subroutine is called during pass1 to create a directory info
770 * entry. During pass1, the passed-in parent is 0; it will get filled
771 * in during pass2.
773 static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
775 struct dx_dir_info *dir;
776 int i, j;
777 errcode_t retval;
778 unsigned long old_size;
780 if (!ctx->dx_dir_info) {
781 ctx->dx_dir_info_count = 0;
782 ctx->dx_dir_info_size = 100; /* Guess */
783 ctx->dx_dir_info = (struct dx_dir_info *)
784 e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
785 * sizeof (struct dx_dir_info),
786 "directory map");
789 if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
790 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
791 ctx->dx_dir_info_size += 10;
792 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
793 sizeof(struct dx_dir_info),
794 &ctx->dx_dir_info);
795 if (retval) {
796 ctx->dx_dir_info_size -= 10;
797 return;
802 * Normally, add_dx_dir_info is called with each inode in
803 * sequential order; but once in a while (like when pass 3
804 * needs to recreate the root directory or lost+found
805 * directory) it is called out of order. In those cases, we
806 * need to move the dx_dir_info entries down to make room, since
807 * the dx_dir_info array needs to be sorted by inode number for
808 * get_dx_dir_info()'s sake.
810 if (ctx->dx_dir_info_count &&
811 ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
812 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
813 if (ctx->dx_dir_info[i-1].ino < ino)
814 break;
815 dir = &ctx->dx_dir_info[i];
816 if (dir->ino != ino)
817 for (j = ctx->dx_dir_info_count++; j > i; j--)
818 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
819 } else
820 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
822 dir->ino = ino;
823 dir->numblocks = num_blocks;
824 dir->hashversion = 0;
825 dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
826 * sizeof (struct dx_dirblock_info),
827 "dx_block info array");
831 * get_dx_dir_info() --- given an inode number, try to find the directory
832 * information entry for it.
834 static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
836 int low, high, mid;
838 low = 0;
839 high = ctx->dx_dir_info_count-1;
840 if (!ctx->dx_dir_info)
841 return 0;
842 if (ino == ctx->dx_dir_info[low].ino)
843 return &ctx->dx_dir_info[low];
844 if (ino == ctx->dx_dir_info[high].ino)
845 return &ctx->dx_dir_info[high];
847 while (low < high) {
848 mid = (low+high)/2;
849 if (mid == low || mid == high)
850 break;
851 if (ino == ctx->dx_dir_info[mid].ino)
852 return &ctx->dx_dir_info[mid];
853 if (ino < ctx->dx_dir_info[mid].ino)
854 high = mid;
855 else
856 low = mid;
858 return 0;
862 * Free the dx_dir_info structure when it isn't needed any more.
864 static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
866 int i;
867 struct dx_dir_info *dir;
869 if (ctx->dx_dir_info) {
870 dir = ctx->dx_dir_info;
871 for (i=0; i < ctx->dx_dir_info_count; i++) {
872 ext2fs_free_mem(&dir->dx_block);
874 ext2fs_free_mem(&ctx->dx_dir_info);
876 ctx->dx_dir_info_size = 0;
877 ctx->dx_dir_info_count = 0;
881 * A simple interator function
883 static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
885 if (*control >= ctx->dx_dir_info_count)
886 return 0;
888 return ctx->dx_dir_info + (*control)++;
891 #endif /* ENABLE_HTREE */
893 * e2fsck.c - a consistency checker for the new extended file system.
898 * This function allocates an e2fsck context
900 static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
902 e2fsck_t context;
903 errcode_t retval;
905 retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
906 if (retval)
907 return retval;
909 memset(context, 0, sizeof(struct e2fsck_struct));
911 context->process_inode_size = 256;
912 context->ext_attr_ver = 2;
914 *ret = context;
915 return 0;
918 struct ea_refcount_el {
919 blk_t ea_blk;
920 int ea_count;
923 struct ea_refcount {
924 blk_t count;
925 blk_t size;
926 blk_t cursor;
927 struct ea_refcount_el *list;
930 static void ea_refcount_free(ext2_refcount_t refcount)
932 if (!refcount)
933 return;
935 ext2fs_free_mem(&refcount->list);
936 ext2fs_free_mem(&refcount);
940 * This function resets an e2fsck context; it is called when e2fsck
941 * needs to be restarted.
943 static errcode_t e2fsck_reset_context(e2fsck_t ctx)
945 ctx->flags = 0;
946 ctx->lost_and_found = 0;
947 ctx->bad_lost_and_found = 0;
948 ext2fs_free_inode_bitmap(ctx->inode_used_map);
949 ctx->inode_used_map = 0;
950 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
951 ctx->inode_dir_map = 0;
952 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
953 ctx->inode_reg_map = 0;
954 ext2fs_free_block_bitmap(ctx->block_found_map);
955 ctx->block_found_map = 0;
956 ext2fs_free_icount(ctx->inode_link_info);
957 ctx->inode_link_info = 0;
958 if (ctx->journal_io) {
959 if (ctx->fs && ctx->fs->io != ctx->journal_io)
960 io_channel_close(ctx->journal_io);
961 ctx->journal_io = 0;
963 if (ctx->fs) {
964 ext2fs_free_dblist(ctx->fs->dblist);
965 ctx->fs->dblist = 0;
967 e2fsck_free_dir_info(ctx);
968 #ifdef ENABLE_HTREE
969 e2fsck_free_dx_dir_info(ctx);
970 #endif
971 ea_refcount_free(ctx->refcount);
972 ctx->refcount = 0;
973 ea_refcount_free(ctx->refcount_extra);
974 ctx->refcount_extra = 0;
975 ext2fs_free_block_bitmap(ctx->block_dup_map);
976 ctx->block_dup_map = 0;
977 ext2fs_free_block_bitmap(ctx->block_ea_map);
978 ctx->block_ea_map = 0;
979 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
980 ctx->inode_bad_map = 0;
981 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
982 ctx->inode_imagic_map = 0;
983 ext2fs_u32_list_free(ctx->dirs_to_hash);
984 ctx->dirs_to_hash = 0;
987 * Clear the array of invalid meta-data flags
989 ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
990 ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
991 ext2fs_free_mem(&ctx->invalid_inode_table_flag);
993 /* Clear statistic counters */
994 ctx->fs_directory_count = 0;
995 ctx->fs_regular_count = 0;
996 ctx->fs_blockdev_count = 0;
997 ctx->fs_chardev_count = 0;
998 ctx->fs_links_count = 0;
999 ctx->fs_symlinks_count = 0;
1000 ctx->fs_fast_symlinks_count = 0;
1001 ctx->fs_fifo_count = 0;
1002 ctx->fs_total_count = 0;
1003 ctx->fs_sockets_count = 0;
1004 ctx->fs_ind_count = 0;
1005 ctx->fs_dind_count = 0;
1006 ctx->fs_tind_count = 0;
1007 ctx->fs_fragmented = 0;
1008 ctx->large_files = 0;
1010 /* Reset the superblock to the user's requested value */
1011 ctx->superblock = ctx->use_superblock;
1013 return 0;
1016 static void e2fsck_free_context(e2fsck_t ctx)
1018 if (!ctx)
1019 return;
1021 e2fsck_reset_context(ctx);
1023 ext2fs_free_mem(&ctx);
1027 * ea_refcount.c
1031 * The strategy we use for keeping track of EA refcounts is as
1032 * follows. We keep a sorted array of first EA blocks and its
1033 * reference counts. Once the refcount has dropped to zero, it is
1034 * removed from the array to save memory space. Once the EA block is
1035 * checked, its bit is set in the block_ea_map bitmap.
1039 static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
1041 ext2_refcount_t refcount;
1042 errcode_t retval;
1043 size_t bytes;
1045 retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
1046 if (retval)
1047 return retval;
1048 memset(refcount, 0, sizeof(struct ea_refcount));
1050 if (!size)
1051 size = 500;
1052 refcount->size = size;
1053 bytes = (size_t) (size * sizeof(struct ea_refcount_el));
1054 #ifdef DEBUG
1055 printf("Refcount allocated %d entries, %d bytes.\n",
1056 refcount->size, bytes);
1057 #endif
1058 retval = ext2fs_get_mem(bytes, &refcount->list);
1059 if (retval)
1060 goto errout;
1061 memset(refcount->list, 0, bytes);
1063 refcount->count = 0;
1064 refcount->cursor = 0;
1066 *ret = refcount;
1067 return 0;
1069 errout:
1070 ea_refcount_free(refcount);
1071 return retval;
1075 * collapse_refcount() --- go through the refcount array, and get rid
1076 * of any count == zero entries
1078 static void refcount_collapse(ext2_refcount_t refcount)
1080 unsigned int i, j;
1081 struct ea_refcount_el *list;
1083 list = refcount->list;
1084 for (i = 0, j = 0; i < refcount->count; i++) {
1085 if (list[i].ea_count) {
1086 if (i != j)
1087 list[j] = list[i];
1088 j++;
1091 #if defined(DEBUG) || defined(TEST_PROGRAM)
1092 printf("Refcount_collapse: size was %d, now %d\n",
1093 refcount->count, j);
1094 #endif
1095 refcount->count = j;
1100 * insert_refcount_el() --- Insert a new entry into the sorted list at a
1101 * specified position.
1103 static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
1104 blk_t blk, int pos)
1106 struct ea_refcount_el *el;
1107 errcode_t retval;
1108 blk_t new_size = 0;
1109 int num;
1111 if (refcount->count >= refcount->size) {
1112 new_size = refcount->size + 100;
1113 #ifdef DEBUG
1114 printf("Reallocating refcount %d entries...\n", new_size);
1115 #endif
1116 retval = ext2fs_resize_mem((size_t) refcount->size *
1117 sizeof(struct ea_refcount_el),
1118 (size_t) new_size *
1119 sizeof(struct ea_refcount_el),
1120 &refcount->list);
1121 if (retval)
1122 return 0;
1123 refcount->size = new_size;
1125 num = (int) refcount->count - pos;
1126 if (num < 0)
1127 return 0; /* should never happen */
1128 if (num) {
1129 memmove(&refcount->list[pos+1], &refcount->list[pos],
1130 sizeof(struct ea_refcount_el) * num);
1132 refcount->count++;
1133 el = &refcount->list[pos];
1134 el->ea_count = 0;
1135 el->ea_blk = blk;
1136 return el;
1141 * get_refcount_el() --- given an block number, try to find refcount
1142 * information in the sorted list. If the create flag is set,
1143 * and we can't find an entry, create one in the sorted list.
1145 static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
1146 blk_t blk, int create)
1148 float range;
1149 int low, high, mid;
1150 blk_t lowval, highval;
1152 if (!refcount || !refcount->list)
1153 return 0;
1154 retry:
1155 low = 0;
1156 high = (int) refcount->count-1;
1157 if (create && ((refcount->count == 0) ||
1158 (blk > refcount->list[high].ea_blk))) {
1159 if (refcount->count >= refcount->size)
1160 refcount_collapse(refcount);
1162 return insert_refcount_el(refcount, blk,
1163 (unsigned) refcount->count);
1165 if (refcount->count == 0)
1166 return 0;
1168 if (refcount->cursor >= refcount->count)
1169 refcount->cursor = 0;
1170 if (blk == refcount->list[refcount->cursor].ea_blk)
1171 return &refcount->list[refcount->cursor++];
1172 #ifdef DEBUG
1173 printf("Non-cursor get_refcount_el: %u\n", blk);
1174 #endif
1175 while (low <= high) {
1176 if (low == high)
1177 mid = low;
1178 else {
1179 /* Interpolate for efficiency */
1180 lowval = refcount->list[low].ea_blk;
1181 highval = refcount->list[high].ea_blk;
1183 if (blk < lowval)
1184 range = 0;
1185 else if (blk > highval)
1186 range = 1;
1187 else
1188 range = ((float) (blk - lowval)) /
1189 (highval - lowval);
1190 mid = low + ((int) (range * (high-low)));
1193 if (blk == refcount->list[mid].ea_blk) {
1194 refcount->cursor = mid+1;
1195 return &refcount->list[mid];
1197 if (blk < refcount->list[mid].ea_blk)
1198 high = mid-1;
1199 else
1200 low = mid+1;
1203 * If we need to create a new entry, it should be right at
1204 * low (where high will be left at low-1).
1206 if (create) {
1207 if (refcount->count >= refcount->size) {
1208 refcount_collapse(refcount);
1209 if (refcount->count < refcount->size)
1210 goto retry;
1212 return insert_refcount_el(refcount, blk, low);
1214 return 0;
1217 static errcode_t
1218 ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
1220 struct ea_refcount_el *el;
1222 el = get_refcount_el(refcount, blk, 1);
1223 if (!el)
1224 return EXT2_ET_NO_MEMORY;
1225 el->ea_count++;
1227 if (ret)
1228 *ret = el->ea_count;
1229 return 0;
1232 static errcode_t
1233 ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
1235 struct ea_refcount_el *el;
1237 el = get_refcount_el(refcount, blk, 0);
1238 if (!el || el->ea_count == 0)
1239 return EXT2_ET_INVALID_ARGUMENT;
1241 el->ea_count--;
1243 if (ret)
1244 *ret = el->ea_count;
1245 return 0;
1248 static errcode_t
1249 ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
1251 struct ea_refcount_el *el;
1254 * Get the refcount element
1256 el = get_refcount_el(refcount, blk, count ? 1 : 0);
1257 if (!el)
1258 return count ? EXT2_ET_NO_MEMORY : 0;
1259 el->ea_count = count;
1260 return 0;
1263 static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
1265 refcount->cursor = 0;
1269 static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
1271 struct ea_refcount_el *list;
1273 while (1) {
1274 if (refcount->cursor >= refcount->count)
1275 return 0;
1276 list = refcount->list;
1277 if (list[refcount->cursor].ea_count) {
1278 if (ret)
1279 *ret = list[refcount->cursor].ea_count;
1280 return list[refcount->cursor++].ea_blk;
1282 refcount->cursor++;
1288 * ehandler.c --- handle bad block errors which come up during the
1289 * course of an e2fsck session.
1293 static const char *operation;
1295 static errcode_t
1296 e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
1297 void *data, size_t size FSCK_ATTR((unused)),
1298 int actual FSCK_ATTR((unused)), errcode_t error)
1300 int i;
1301 char *p;
1302 ext2_filsys fs = (ext2_filsys) channel->app_data;
1303 e2fsck_t ctx;
1305 ctx = (e2fsck_t) fs->priv_data;
1308 * If more than one block was read, try reading each block
1309 * separately. We could use the actual bytes read to figure
1310 * out where to start, but we don't bother.
1312 if (count > 1) {
1313 p = (char *) data;
1314 for (i=0; i < count; i++, p += channel->block_size, block++) {
1315 error = io_channel_read_blk(channel, block,
1316 1, p);
1317 if (error)
1318 return error;
1320 return 0;
1322 if (operation)
1323 printf(_("Error reading block %lu (%s) while %s. "), block,
1324 error_message(error), operation);
1325 else
1326 printf(_("Error reading block %lu (%s). "), block,
1327 error_message(error));
1328 preenhalt(ctx);
1329 if (ask(ctx, _("Ignore error"), 1)) {
1330 if (ask(ctx, _("Force rewrite"), 1))
1331 io_channel_write_blk(channel, block, 1, data);
1332 return 0;
1335 return error;
1338 static errcode_t
1339 e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
1340 const void *data, size_t size FSCK_ATTR((unused)),
1341 int actual FSCK_ATTR((unused)), errcode_t error)
1343 int i;
1344 const char *p;
1345 ext2_filsys fs = (ext2_filsys) channel->app_data;
1346 e2fsck_t ctx;
1348 ctx = (e2fsck_t) fs->priv_data;
1351 * If more than one block was written, try writing each block
1352 * separately. We could use the actual bytes read to figure
1353 * out where to start, but we don't bother.
1355 if (count > 1) {
1356 p = (const char *) data;
1357 for (i=0; i < count; i++, p += channel->block_size, block++) {
1358 error = io_channel_write_blk(channel, block,
1359 1, p);
1360 if (error)
1361 return error;
1363 return 0;
1366 if (operation)
1367 printf(_("Error writing block %lu (%s) while %s. "), block,
1368 error_message(error), operation);
1369 else
1370 printf(_("Error writing block %lu (%s). "), block,
1371 error_message(error));
1372 preenhalt(ctx);
1373 if (ask(ctx, _("Ignore error"), 1))
1374 return 0;
1376 return error;
1379 static const char *ehandler_operation(const char *op)
1381 const char *ret = operation;
1383 operation = op;
1384 return ret;
1387 static void ehandler_init(io_channel channel)
1389 channel->read_error = e2fsck_handle_read_error;
1390 channel->write_error = e2fsck_handle_write_error;
1394 * journal.c --- code for handling the "ext3" journal
1396 * Copyright (C) 2000 Andreas Dilger
1397 * Copyright (C) 2000 Theodore Ts'o
1399 * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
1400 * Copyright (C) 1999 Red Hat Software
1402 * This file may be redistributed under the terms of the
1403 * GNU General Public License version 2 or at your discretion
1404 * any later version.
1408 * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
1409 * This creates a larger static binary, and a smaller binary using
1410 * shared libraries. It's also probably slightly less CPU-efficient,
1411 * which is why it's not on by default. But, it's a good way of
1412 * testing the functions in inode_io.c and fileio.c.
1414 #undef USE_INODE_IO
1416 /* Kernel compatibility functions for handling the journal. These allow us
1417 * to use the recovery.c file virtually unchanged from the kernel, so we
1418 * don't have to do much to keep kernel and user recovery in sync.
1420 static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
1422 #ifdef USE_INODE_IO
1423 *phys = block;
1424 return 0;
1425 #else
1426 struct inode *inode = journal->j_inode;
1427 errcode_t retval;
1428 blk_t pblk;
1430 if (!inode) {
1431 *phys = block;
1432 return 0;
1435 retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
1436 &inode->i_ext2, NULL, 0, block, &pblk);
1437 *phys = pblk;
1438 return retval;
1439 #endif
1442 static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
1444 struct buffer_head *bh;
1446 bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
1447 if (!bh)
1448 return NULL;
1450 bh->b_ctx = kdev->k_ctx;
1451 if (kdev->k_dev == K_DEV_FS)
1452 bh->b_io = kdev->k_ctx->fs->io;
1453 else
1454 bh->b_io = kdev->k_ctx->journal_io;
1455 bh->b_size = blocksize;
1456 bh->b_blocknr = blocknr;
1458 return bh;
1461 static void sync_blockdev(kdev_t kdev)
1463 io_channel io;
1465 if (kdev->k_dev == K_DEV_FS)
1466 io = kdev->k_ctx->fs->io;
1467 else
1468 io = kdev->k_ctx->journal_io;
1470 io_channel_flush(io);
1473 static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
1475 int retval;
1476 struct buffer_head *bh;
1478 for (; nr > 0; --nr) {
1479 bh = *bhp++;
1480 if (rw == READ && !bh->b_uptodate) {
1481 retval = io_channel_read_blk(bh->b_io,
1482 bh->b_blocknr,
1483 1, bh->b_data);
1484 if (retval) {
1485 bb_error_msg("while reading block %lu",
1486 (unsigned long) bh->b_blocknr);
1487 bh->b_err = retval;
1488 continue;
1490 bh->b_uptodate = 1;
1491 } else if (rw == WRITE && bh->b_dirty) {
1492 retval = io_channel_write_blk(bh->b_io,
1493 bh->b_blocknr,
1494 1, bh->b_data);
1495 if (retval) {
1496 bb_error_msg("while writing block %lu",
1497 (unsigned long) bh->b_blocknr);
1498 bh->b_err = retval;
1499 continue;
1501 bh->b_dirty = 0;
1502 bh->b_uptodate = 1;
1507 static void mark_buffer_dirty(struct buffer_head *bh)
1509 bh->b_dirty = 1;
1512 static inline void mark_buffer_clean(struct buffer_head * bh)
1514 bh->b_dirty = 0;
1517 static void brelse(struct buffer_head *bh)
1519 if (bh->b_dirty)
1520 ll_rw_block(WRITE, 1, &bh);
1521 ext2fs_free_mem(&bh);
1524 static int buffer_uptodate(struct buffer_head *bh)
1526 return bh->b_uptodate;
1529 static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
1531 bh->b_uptodate = val;
1534 static void wait_on_buffer(struct buffer_head *bh)
1536 if (!bh->b_uptodate)
1537 ll_rw_block(READ, 1, &bh);
1541 static void e2fsck_clear_recover(e2fsck_t ctx, int error)
1543 ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
1545 /* if we had an error doing journal recovery, we need a full fsck */
1546 if (error)
1547 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
1548 ext2fs_mark_super_dirty(ctx->fs);
1551 static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
1553 struct ext2_super_block *sb = ctx->fs->super;
1554 struct ext2_super_block jsuper;
1555 struct problem_context pctx;
1556 struct buffer_head *bh;
1557 struct inode *j_inode = NULL;
1558 struct kdev_s *dev_fs = NULL, *dev_journal;
1559 const char *journal_name = NULL;
1560 journal_t *journal = NULL;
1561 errcode_t retval = 0;
1562 io_manager io_ptr = 0;
1563 unsigned long start = 0;
1564 blk_t blk;
1565 int ext_journal = 0;
1566 int tried_backup_jnl = 0;
1567 int i;
1569 clear_problem_context(&pctx);
1571 journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
1572 if (!journal) {
1573 return EXT2_ET_NO_MEMORY;
1576 dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
1577 if (!dev_fs) {
1578 retval = EXT2_ET_NO_MEMORY;
1579 goto errout;
1581 dev_journal = dev_fs+1;
1583 dev_fs->k_ctx = dev_journal->k_ctx = ctx;
1584 dev_fs->k_dev = K_DEV_FS;
1585 dev_journal->k_dev = K_DEV_JOURNAL;
1587 journal->j_dev = dev_journal;
1588 journal->j_fs_dev = dev_fs;
1589 journal->j_inode = NULL;
1590 journal->j_blocksize = ctx->fs->blocksize;
1592 if (uuid_is_null(sb->s_journal_uuid)) {
1593 if (!sb->s_journal_inum)
1594 return EXT2_ET_BAD_INODE_NUM;
1595 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
1596 "journal inode");
1597 if (!j_inode) {
1598 retval = EXT2_ET_NO_MEMORY;
1599 goto errout;
1602 j_inode->i_ctx = ctx;
1603 j_inode->i_ino = sb->s_journal_inum;
1605 if ((retval = ext2fs_read_inode(ctx->fs,
1606 sb->s_journal_inum,
1607 &j_inode->i_ext2))) {
1608 try_backup_journal:
1609 if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
1610 tried_backup_jnl)
1611 goto errout;
1612 memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
1613 memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
1614 EXT2_N_BLOCKS*4);
1615 j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
1616 j_inode->i_ext2.i_links_count = 1;
1617 j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
1618 tried_backup_jnl++;
1620 if (!j_inode->i_ext2.i_links_count ||
1621 !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
1622 retval = EXT2_ET_NO_JOURNAL;
1623 goto try_backup_journal;
1625 if (j_inode->i_ext2.i_size / journal->j_blocksize <
1626 JFS_MIN_JOURNAL_BLOCKS) {
1627 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1628 goto try_backup_journal;
1630 for (i=0; i < EXT2_N_BLOCKS; i++) {
1631 blk = j_inode->i_ext2.i_block[i];
1632 if (!blk) {
1633 if (i < EXT2_NDIR_BLOCKS) {
1634 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1635 goto try_backup_journal;
1637 continue;
1639 if (blk < sb->s_first_data_block ||
1640 blk >= sb->s_blocks_count) {
1641 retval = EXT2_ET_BAD_BLOCK_NUM;
1642 goto try_backup_journal;
1645 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
1647 #ifdef USE_INODE_IO
1648 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
1649 &j_inode->i_ext2,
1650 &journal_name);
1651 if (retval)
1652 goto errout;
1654 io_ptr = inode_io_manager;
1655 #else
1656 journal->j_inode = j_inode;
1657 ctx->journal_io = ctx->fs->io;
1658 if ((retval = journal_bmap(journal, 0, &start)) != 0)
1659 goto errout;
1660 #endif
1661 } else {
1662 ext_journal = 1;
1663 if (!ctx->journal_name) {
1664 char uuid[37];
1666 unparse_uuid(sb->s_journal_uuid, uuid);
1667 ctx->journal_name = get_devname_from_uuid(uuid);
1668 if (!ctx->journal_name)
1669 ctx->journal_name = get_devname_from_device(sb->s_journal_dev);
1671 journal_name = ctx->journal_name;
1673 if (!journal_name) {
1674 fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
1675 return EXT2_ET_LOAD_EXT_JOURNAL;
1678 io_ptr = unix_io_manager;
1681 #ifndef USE_INODE_IO
1682 if (ext_journal)
1683 #endif
1684 retval = io_ptr->open(journal_name, IO_FLAG_RW,
1685 &ctx->journal_io);
1686 if (retval)
1687 goto errout;
1689 io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
1691 if (ext_journal) {
1692 if (ctx->fs->blocksize == 1024)
1693 start = 1;
1694 bh = getblk(dev_journal, start, ctx->fs->blocksize);
1695 if (!bh) {
1696 retval = EXT2_ET_NO_MEMORY;
1697 goto errout;
1699 ll_rw_block(READ, 1, &bh);
1700 if ((retval = bh->b_err) != 0)
1701 goto errout;
1702 memcpy(&jsuper, start ? bh->b_data : bh->b_data + 1024,
1703 sizeof(jsuper));
1704 brelse(bh);
1705 #if BB_BIG_ENDIAN
1706 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
1707 ext2fs_swap_super(&jsuper);
1708 #endif
1709 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
1710 !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
1711 fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
1712 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1713 goto errout;
1715 /* Make sure the journal UUID is correct */
1716 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
1717 sizeof(jsuper.s_uuid))) {
1718 fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
1719 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1720 goto errout;
1723 journal->j_maxlen = jsuper.s_blocks_count;
1724 start++;
1727 if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
1728 retval = EXT2_ET_NO_MEMORY;
1729 goto errout;
1732 journal->j_sb_buffer = bh;
1733 journal->j_superblock = (journal_superblock_t *)bh->b_data;
1735 #ifdef USE_INODE_IO
1736 ext2fs_free_mem(&j_inode);
1737 #endif
1739 *ret_journal = journal;
1740 return 0;
1742 errout:
1743 ext2fs_free_mem(&dev_fs);
1744 ext2fs_free_mem(&j_inode);
1745 ext2fs_free_mem(&journal);
1746 return retval;
1749 static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
1750 struct problem_context *pctx)
1752 struct ext2_super_block *sb = ctx->fs->super;
1753 int recover = ctx->fs->super->s_feature_incompat &
1754 EXT3_FEATURE_INCOMPAT_RECOVER;
1755 int has_journal = ctx->fs->super->s_feature_compat &
1756 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1758 if (has_journal || sb->s_journal_inum) {
1759 /* The journal inode is bogus, remove and force full fsck */
1760 pctx->ino = sb->s_journal_inum;
1761 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
1762 if (has_journal && sb->s_journal_inum)
1763 printf("*** ext3 journal has been deleted - "
1764 "filesystem is now ext2 only ***\n\n");
1765 sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1766 sb->s_journal_inum = 0;
1767 ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
1768 e2fsck_clear_recover(ctx, 1);
1769 return 0;
1771 return EXT2_ET_BAD_INODE_NUM;
1772 } else if (recover) {
1773 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
1774 e2fsck_clear_recover(ctx, 1);
1775 return 0;
1777 return EXT2_ET_UNSUPP_FEATURE;
1779 return 0;
1782 #define V1_SB_SIZE 0x0024
1783 static void clear_v2_journal_fields(journal_t *journal)
1785 e2fsck_t ctx = journal->j_dev->k_ctx;
1786 struct problem_context pctx;
1788 clear_problem_context(&pctx);
1790 if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
1791 return;
1793 memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
1794 ctx->fs->blocksize-V1_SB_SIZE);
1795 mark_buffer_dirty(journal->j_sb_buffer);
1799 static errcode_t e2fsck_journal_load(journal_t *journal)
1801 e2fsck_t ctx = journal->j_dev->k_ctx;
1802 journal_superblock_t *jsb;
1803 struct buffer_head *jbh = journal->j_sb_buffer;
1804 struct problem_context pctx;
1806 clear_problem_context(&pctx);
1808 ll_rw_block(READ, 1, &jbh);
1809 if (jbh->b_err) {
1810 bb_error_msg(_("reading journal superblock"));
1811 return jbh->b_err;
1814 jsb = journal->j_superblock;
1815 /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
1816 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
1817 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1819 switch (ntohl(jsb->s_header.h_blocktype)) {
1820 case JFS_SUPERBLOCK_V1:
1821 journal->j_format_version = 1;
1822 if (jsb->s_feature_compat ||
1823 jsb->s_feature_incompat ||
1824 jsb->s_feature_ro_compat ||
1825 jsb->s_nr_users)
1826 clear_v2_journal_fields(journal);
1827 break;
1829 case JFS_SUPERBLOCK_V2:
1830 journal->j_format_version = 2;
1831 if (ntohl(jsb->s_nr_users) > 1 &&
1832 uuid_is_null(ctx->fs->super->s_journal_uuid))
1833 clear_v2_journal_fields(journal);
1834 if (ntohl(jsb->s_nr_users) > 1) {
1835 fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
1836 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1838 break;
1841 * These should never appear in a journal super block, so if
1842 * they do, the journal is badly corrupted.
1844 case JFS_DESCRIPTOR_BLOCK:
1845 case JFS_COMMIT_BLOCK:
1846 case JFS_REVOKE_BLOCK:
1847 return EXT2_ET_CORRUPT_SUPERBLOCK;
1849 /* If we don't understand the superblock major type, but there
1850 * is a magic number, then it is likely to be a new format we
1851 * just don't understand, so leave it alone. */
1852 default:
1853 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1856 if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
1857 return EXT2_ET_UNSUPP_FEATURE;
1859 if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
1860 return EXT2_ET_RO_UNSUPP_FEATURE;
1862 /* We have now checked whether we know enough about the journal
1863 * format to be able to proceed safely, so any other checks that
1864 * fail we should attempt to recover from. */
1865 if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
1866 bb_error_msg(_("%s: no valid journal superblock found"),
1867 ctx->device_name);
1868 return EXT2_ET_CORRUPT_SUPERBLOCK;
1871 if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
1872 journal->j_maxlen = ntohl(jsb->s_maxlen);
1873 else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
1874 bb_error_msg(_("%s: journal too short"),
1875 ctx->device_name);
1876 return EXT2_ET_CORRUPT_SUPERBLOCK;
1879 journal->j_tail_sequence = ntohl(jsb->s_sequence);
1880 journal->j_transaction_sequence = journal->j_tail_sequence;
1881 journal->j_tail = ntohl(jsb->s_start);
1882 journal->j_first = ntohl(jsb->s_first);
1883 journal->j_last = ntohl(jsb->s_maxlen);
1885 return 0;
1888 static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
1889 journal_t *journal)
1891 char *p;
1892 union {
1893 __u8 uuid[16];
1894 __u32 val[4];
1895 } u;
1896 __u32 new_seq = 0;
1897 int i;
1899 /* Leave a valid existing V1 superblock signature alone.
1900 * Anything unrecognizable we overwrite with a new V2
1901 * signature. */
1903 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
1904 jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
1905 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
1906 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
1909 /* Zero out everything else beyond the superblock header */
1911 p = ((char *) jsb) + sizeof(journal_header_t);
1912 memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
1914 jsb->s_blocksize = htonl(ctx->fs->blocksize);
1915 jsb->s_maxlen = htonl(journal->j_maxlen);
1916 jsb->s_first = htonl(1);
1918 /* Initialize the journal sequence number so that there is "no"
1919 * chance we will find old "valid" transactions in the journal.
1920 * This avoids the need to zero the whole journal (slow to do,
1921 * and risky when we are just recovering the filesystem).
1923 generate_uuid(u.uuid);
1924 for (i = 0; i < 4; i ++)
1925 new_seq ^= u.val[i];
1926 jsb->s_sequence = htonl(new_seq);
1928 mark_buffer_dirty(journal->j_sb_buffer);
1929 ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
1932 static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
1933 journal_t *journal,
1934 struct problem_context *pctx)
1936 struct ext2_super_block *sb = ctx->fs->super;
1937 int recover = ctx->fs->super->s_feature_incompat &
1938 EXT3_FEATURE_INCOMPAT_RECOVER;
1940 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1941 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
1942 e2fsck_journal_reset_super(ctx, journal->j_superblock,
1943 journal);
1944 journal->j_transaction_sequence = 1;
1945 e2fsck_clear_recover(ctx, recover);
1946 return 0;
1948 return EXT2_ET_CORRUPT_SUPERBLOCK;
1949 } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
1950 return EXT2_ET_CORRUPT_SUPERBLOCK;
1952 return 0;
1955 static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
1956 int reset, int drop)
1958 journal_superblock_t *jsb;
1960 if (drop)
1961 mark_buffer_clean(journal->j_sb_buffer);
1962 else if (!(ctx->options & E2F_OPT_READONLY)) {
1963 jsb = journal->j_superblock;
1964 jsb->s_sequence = htonl(journal->j_transaction_sequence);
1965 if (reset)
1966 jsb->s_start = 0; /* this marks the journal as empty */
1967 mark_buffer_dirty(journal->j_sb_buffer);
1969 brelse(journal->j_sb_buffer);
1971 if (ctx->journal_io) {
1972 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1973 io_channel_close(ctx->journal_io);
1974 ctx->journal_io = 0;
1977 #ifndef USE_INODE_IO
1978 ext2fs_free_mem(&journal->j_inode);
1979 #endif
1980 ext2fs_free_mem(&journal->j_fs_dev);
1981 ext2fs_free_mem(&journal);
1985 * This function makes sure that the superblock fields regarding the
1986 * journal are consistent.
1988 static int e2fsck_check_ext3_journal(e2fsck_t ctx)
1990 struct ext2_super_block *sb = ctx->fs->super;
1991 journal_t *journal;
1992 int recover = ctx->fs->super->s_feature_incompat &
1993 EXT3_FEATURE_INCOMPAT_RECOVER;
1994 struct problem_context pctx;
1995 problem_t problem;
1996 int reset = 0, force_fsck = 0;
1997 int retval;
1999 /* If we don't have any journal features, don't do anything more */
2000 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
2001 !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
2002 uuid_is_null(sb->s_journal_uuid))
2003 return 0;
2005 clear_problem_context(&pctx);
2006 pctx.num = sb->s_journal_inum;
2008 retval = e2fsck_get_journal(ctx, &journal);
2009 if (retval) {
2010 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
2011 (retval == EXT2_ET_BAD_BLOCK_NUM) ||
2012 (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
2013 (retval == EXT2_ET_NO_JOURNAL))
2014 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
2015 return retval;
2018 retval = e2fsck_journal_load(journal);
2019 if (retval) {
2020 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
2021 ((retval == EXT2_ET_UNSUPP_FEATURE) &&
2022 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
2023 &pctx))) ||
2024 ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
2025 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
2026 &pctx))) ||
2027 ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
2028 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
2029 retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
2030 &pctx);
2031 e2fsck_journal_release(ctx, journal, 0, 1);
2032 return retval;
2036 * We want to make the flags consistent here. We will not leave with
2037 * needs_recovery set but has_journal clear. We can't get in a loop
2038 * with -y, -n, or -p, only if a user isn't making up their mind.
2040 no_has_journal:
2041 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
2042 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
2043 pctx.str = "inode";
2044 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
2045 if (recover &&
2046 !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
2047 goto no_has_journal;
2049 * Need a full fsck if we are releasing a
2050 * journal stored on a reserved inode.
2052 force_fsck = recover ||
2053 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
2054 /* Clear all of the journal fields */
2055 sb->s_journal_inum = 0;
2056 sb->s_journal_dev = 0;
2057 memset(sb->s_journal_uuid, 0,
2058 sizeof(sb->s_journal_uuid));
2059 e2fsck_clear_recover(ctx, force_fsck);
2060 } else if (!(ctx->options & E2F_OPT_READONLY)) {
2061 sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2062 ext2fs_mark_super_dirty(ctx->fs);
2066 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
2067 !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
2068 journal->j_superblock->s_start != 0) {
2069 /* Print status information */
2070 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
2071 if (ctx->superblock)
2072 problem = PR_0_JOURNAL_RUN_DEFAULT;
2073 else
2074 problem = PR_0_JOURNAL_RUN;
2075 if (fix_problem(ctx, problem, &pctx)) {
2076 ctx->options |= E2F_OPT_FORCE;
2077 sb->s_feature_incompat |=
2078 EXT3_FEATURE_INCOMPAT_RECOVER;
2079 ext2fs_mark_super_dirty(ctx->fs);
2080 } else if (fix_problem(ctx,
2081 PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
2082 reset = 1;
2083 sb->s_state &= ~EXT2_VALID_FS;
2084 ext2fs_mark_super_dirty(ctx->fs);
2087 * If the user answers no to the above question, we
2088 * ignore the fact that journal apparently has data;
2089 * accidentally replaying over valid data would be far
2090 * worse than skipping a questionable recovery.
2092 * XXX should we abort with a fatal error here? What
2093 * will the ext3 kernel code do if a filesystem with
2094 * !NEEDS_RECOVERY but with a non-zero
2095 * journal->j_superblock->s_start is mounted?
2099 e2fsck_journal_release(ctx, journal, reset, 0);
2100 return retval;
2103 static errcode_t recover_ext3_journal(e2fsck_t ctx)
2105 journal_t *journal;
2106 int retval;
2108 journal_init_revoke_caches();
2109 retval = e2fsck_get_journal(ctx, &journal);
2110 if (retval)
2111 return retval;
2113 retval = e2fsck_journal_load(journal);
2114 if (retval)
2115 goto errout;
2117 retval = journal_init_revoke(journal, 1024);
2118 if (retval)
2119 goto errout;
2121 retval = -journal_recover(journal);
2122 if (retval)
2123 goto errout;
2125 if (journal->j_superblock->s_errno) {
2126 ctx->fs->super->s_state |= EXT2_ERROR_FS;
2127 ext2fs_mark_super_dirty(ctx->fs);
2128 journal->j_superblock->s_errno = 0;
2129 mark_buffer_dirty(journal->j_sb_buffer);
2132 errout:
2133 journal_destroy_revoke(journal);
2134 journal_destroy_revoke_caches();
2135 e2fsck_journal_release(ctx, journal, 1, 0);
2136 return retval;
2139 static int e2fsck_run_ext3_journal(e2fsck_t ctx)
2141 io_manager io_ptr = ctx->fs->io->manager;
2142 int blocksize = ctx->fs->blocksize;
2143 errcode_t retval, recover_retval;
2145 printf(_("%s: recovering journal\n"), ctx->device_name);
2146 if (ctx->options & E2F_OPT_READONLY) {
2147 printf(_("%s: won't do journal recovery while read-only\n"),
2148 ctx->device_name);
2149 return EXT2_ET_FILE_RO;
2152 if (ctx->fs->flags & EXT2_FLAG_DIRTY)
2153 ext2fs_flush(ctx->fs); /* Force out any modifications */
2155 recover_retval = recover_ext3_journal(ctx);
2158 * Reload the filesystem context to get up-to-date data from disk
2159 * because journal recovery will change the filesystem under us.
2161 ext2fs_close(ctx->fs);
2162 retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
2163 ctx->superblock, blocksize, io_ptr,
2164 &ctx->fs);
2166 if (retval) {
2167 bb_error_msg(_("while trying to re-open %s"),
2168 ctx->device_name);
2169 bb_error_msg_and_die(0);
2171 ctx->fs->priv_data = ctx;
2173 /* Set the superblock flags */
2174 e2fsck_clear_recover(ctx, recover_retval);
2175 return recover_retval;
2179 * This function will move the journal inode from a visible file in
2180 * the filesystem directory hierarchy to the reserved inode if necessary.
2182 static const char *const journal_names[] = {
2183 ".journal", "journal", ".journal.dat", "journal.dat", 0 };
2185 static void e2fsck_move_ext3_journal(e2fsck_t ctx)
2187 struct ext2_super_block *sb = ctx->fs->super;
2188 struct problem_context pctx;
2189 struct ext2_inode inode;
2190 ext2_filsys fs = ctx->fs;
2191 ext2_ino_t ino;
2192 errcode_t retval;
2193 const char *const * cpp;
2194 int group, mount_flags;
2196 clear_problem_context(&pctx);
2199 * If the filesystem is opened read-only, or there is no
2200 * journal, then do nothing.
2202 if ((ctx->options & E2F_OPT_READONLY) ||
2203 (sb->s_journal_inum == 0) ||
2204 !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2205 return;
2208 * Read in the journal inode
2210 if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
2211 return;
2214 * If it's necessary to backup the journal inode, do so.
2216 if ((sb->s_jnl_backup_type == 0) ||
2217 ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
2218 memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
2219 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
2220 memcpy(sb->s_jnl_blocks, inode.i_block,
2221 EXT2_N_BLOCKS*4);
2222 sb->s_jnl_blocks[16] = inode.i_size;
2223 sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2224 ext2fs_mark_super_dirty(fs);
2225 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2230 * If the journal is already the hidden inode, then do nothing
2232 if (sb->s_journal_inum == EXT2_JOURNAL_INO)
2233 return;
2236 * The journal inode had better have only one link and not be readable.
2238 if (inode.i_links_count != 1)
2239 return;
2242 * If the filesystem is mounted, or we can't tell whether
2243 * or not it's mounted, do nothing.
2245 retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
2246 if (retval || (mount_flags & EXT2_MF_MOUNTED))
2247 return;
2250 * If we can't find the name of the journal inode, then do
2251 * nothing.
2253 for (cpp = journal_names; *cpp; cpp++) {
2254 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
2255 strlen(*cpp), 0, &ino);
2256 if ((retval == 0) && (ino == sb->s_journal_inum))
2257 break;
2259 if (*cpp == 0)
2260 return;
2262 /* We need the inode bitmap to be loaded */
2263 retval = ext2fs_read_bitmaps(fs);
2264 if (retval)
2265 return;
2267 pctx.str = *cpp;
2268 if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
2269 return;
2272 * OK, we've done all the checks, let's actually move the
2273 * journal inode. Errors at this point mean we need to force
2274 * an ext2 filesystem check.
2276 if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
2277 goto err_out;
2278 if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
2279 goto err_out;
2280 sb->s_journal_inum = EXT2_JOURNAL_INO;
2281 ext2fs_mark_super_dirty(fs);
2282 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2283 inode.i_links_count = 0;
2284 inode.i_dtime = time(NULL);
2285 if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
2286 goto err_out;
2288 group = ext2fs_group_of_ino(fs, ino);
2289 ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
2290 ext2fs_mark_ib_dirty(fs);
2291 fs->group_desc[group].bg_free_inodes_count++;
2292 fs->super->s_free_inodes_count++;
2293 return;
2295 err_out:
2296 pctx.errcode = retval;
2297 fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
2298 fs->super->s_state &= ~EXT2_VALID_FS;
2299 ext2fs_mark_super_dirty(fs);
2303 * message.c --- print e2fsck messages (with compression)
2305 * print_e2fsck_message() prints a message to the user, using
2306 * compression techniques and expansions of abbreviations.
2308 * The following % expansions are supported:
2310 * %b <blk> block number
2311 * %B <blkcount> integer
2312 * %c <blk2> block number
2313 * %Di <dirent>->ino inode number
2314 * %Dn <dirent>->name string
2315 * %Dr <dirent>->rec_len
2316 * %Dl <dirent>->name_len
2317 * %Dt <dirent>->filetype
2318 * %d <dir> inode number
2319 * %g <group> integer
2320 * %i <ino> inode number
2321 * %Is <inode> -> i_size
2322 * %IS <inode> -> i_extra_isize
2323 * %Ib <inode> -> i_blocks
2324 * %Il <inode> -> i_links_count
2325 * %Im <inode> -> i_mode
2326 * %IM <inode> -> i_mtime
2327 * %IF <inode> -> i_faddr
2328 * %If <inode> -> i_file_acl
2329 * %Id <inode> -> i_dir_acl
2330 * %Iu <inode> -> i_uid
2331 * %Ig <inode> -> i_gid
2332 * %j <ino2> inode number
2333 * %m <com_err error message>
2334 * %N <num>
2335 * %p ext2fs_get_pathname of directory <ino>
2336 * %P ext2fs_get_pathname of <dirent>->ino with <ino2> as
2337 * the containing directory. (If dirent is NULL
2338 * then return the pathname of directory <ino2>)
2339 * %q ext2fs_get_pathname of directory <dir>
2340 * %Q ext2fs_get_pathname of directory <ino> with <dir> as
2341 * the containing directory.
2342 * %s <str> miscellaneous string
2343 * %S backup superblock
2344 * %X <num> hexadecimal format
2346 * The following '@' expansions are supported:
2348 * @a extended attribute
2349 * @A error allocating
2350 * @b block
2351 * @B bitmap
2352 * @c compress
2353 * @C conflicts with some other fs block
2354 * @D deleted
2355 * @d directory
2356 * @e entry
2357 * @E Entry '%Dn' in %p (%i)
2358 * @f filesystem
2359 * @F for @i %i (%Q) is
2360 * @g group
2361 * @h HTREE directory inode
2362 * @i inode
2363 * @I illegal
2364 * @j journal
2365 * @l lost+found
2366 * @L is a link
2367 * @m multiply-claimed
2368 * @n invalid
2369 * @o orphaned
2370 * @p problem in
2371 * @r root inode
2372 * @s should be
2373 * @S superblock
2374 * @u unattached
2375 * @v device
2376 * @z zero-length
2381 * This structure defines the abbreviations used by the text strings
2382 * below. The first character in the string is the index letter. An
2383 * abbreviation of the form '@<i>' is expanded by looking up the index
2384 * letter <i> in the table below.
2386 static const char *const abbrevs[] = {
2387 N_("aextended attribute"),
2388 N_("Aerror allocating"),
2389 N_("bblock"),
2390 N_("Bbitmap"),
2391 N_("ccompress"),
2392 N_("Cconflicts with some other fs @b"),
2393 N_("iinode"),
2394 N_("Iillegal"),
2395 N_("jjournal"),
2396 N_("Ddeleted"),
2397 N_("ddirectory"),
2398 N_("eentry"),
2399 N_("E@e '%Dn' in %p (%i)"),
2400 N_("ffilesystem"),
2401 N_("Ffor @i %i (%Q) is"),
2402 N_("ggroup"),
2403 N_("hHTREE @d @i"),
2404 N_("llost+found"),
2405 N_("Lis a link"),
2406 N_("mmultiply-claimed"),
2407 N_("ninvalid"),
2408 N_("oorphaned"),
2409 N_("pproblem in"),
2410 N_("rroot @i"),
2411 N_("sshould be"),
2412 N_("Ssuper@b"),
2413 N_("uunattached"),
2414 N_("vdevice"),
2415 N_("zzero-length"),
2416 "@@",
2421 * Give more user friendly names to the "special" inodes.
2423 #define num_special_inodes 11
2424 static const char *const special_inode_name[] =
2426 N_("<The NULL inode>"), /* 0 */
2427 N_("<The bad blocks inode>"), /* 1 */
2428 "/", /* 2 */
2429 N_("<The ACL index inode>"), /* 3 */
2430 N_("<The ACL data inode>"), /* 4 */
2431 N_("<The boot loader inode>"), /* 5 */
2432 N_("<The undelete directory inode>"), /* 6 */
2433 N_("<The group descriptor inode>"), /* 7 */
2434 N_("<The journal inode>"), /* 8 */
2435 N_("<Reserved inode 9>"), /* 9 */
2436 N_("<Reserved inode 10>"), /* 10 */
2440 * This function does "safe" printing. It will convert non-printable
2441 * ASCII characters using '^' and M- notation.
2443 static void safe_print(const char *cp, int len)
2445 unsigned char ch;
2447 if (len < 0)
2448 len = strlen(cp);
2450 while (len--) {
2451 ch = *cp++;
2452 if (ch > 128) {
2453 fputs("M-", stdout);
2454 ch -= 128;
2456 if ((ch < 32) || (ch == 0x7f)) {
2457 bb_putchar('^');
2458 ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
2460 bb_putchar(ch);
2466 * This function prints a pathname, using the ext2fs_get_pathname
2467 * function
2469 static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
2471 errcode_t retval;
2472 char *path;
2474 if (!dir && (ino < num_special_inodes)) {
2475 fputs(_(special_inode_name[ino]), stdout);
2476 return;
2479 retval = ext2fs_get_pathname(fs, dir, ino, &path);
2480 if (retval)
2481 fputs("???", stdout);
2482 else {
2483 safe_print(path, -1);
2484 ext2fs_free_mem(&path);
2488 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2489 struct problem_context *pctx, int first);
2491 * This function handles the '@' expansion. We allow recursive
2492 * expansion; an @ expression can contain further '@' and '%'
2493 * expressions.
2495 static void expand_at_expression(e2fsck_t ctx, char ch,
2496 struct problem_context *pctx,
2497 int *first)
2499 const char *const *cpp;
2500 const char *str;
2502 /* Search for the abbreviation */
2503 for (cpp = abbrevs; *cpp; cpp++) {
2504 if (ch == *cpp[0])
2505 break;
2507 if (*cpp) {
2508 str = _(*cpp) + 1;
2509 if (*first && islower(*str)) {
2510 *first = 0;
2511 bb_putchar(toupper(*str++));
2513 print_e2fsck_message(ctx, str, pctx, *first);
2514 } else
2515 printf("@%c", ch);
2519 * This function expands '%IX' expressions
2521 static void expand_inode_expression(char ch,
2522 struct problem_context *ctx)
2524 struct ext2_inode *inode;
2525 struct ext2_inode_large *large_inode;
2526 char * time_str;
2527 time_t t;
2528 int do_gmt = -1;
2530 if (!ctx || !ctx->inode)
2531 goto no_inode;
2533 inode = ctx->inode;
2534 large_inode = (struct ext2_inode_large *) inode;
2536 switch (ch) {
2537 case 's':
2538 if (LINUX_S_ISDIR(inode->i_mode))
2539 printf("%u", inode->i_size);
2540 else {
2541 printf("%"PRIu64, (inode->i_size |
2542 ((uint64_t) inode->i_size_high << 32)));
2544 break;
2545 case 'S':
2546 printf("%u", large_inode->i_extra_isize);
2547 break;
2548 case 'b':
2549 printf("%u", inode->i_blocks);
2550 break;
2551 case 'l':
2552 printf("%d", inode->i_links_count);
2553 break;
2554 case 'm':
2555 printf("0%o", inode->i_mode);
2556 break;
2557 case 'M':
2558 /* The diet libc doesn't respect the TZ environemnt variable */
2559 if (do_gmt == -1) {
2560 time_str = getenv("TZ");
2561 if (!time_str)
2562 time_str = (char *)"";
2563 do_gmt = !strcmp(time_str, "GMT");
2565 t = inode->i_mtime;
2566 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
2567 printf("%.24s", time_str);
2568 break;
2569 case 'F':
2570 printf("%u", inode->i_faddr);
2571 break;
2572 case 'f':
2573 printf("%u", inode->i_file_acl);
2574 break;
2575 case 'd':
2576 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
2577 inode->i_dir_acl : 0));
2578 break;
2579 case 'u':
2580 printf("%d", (inode->i_uid |
2581 (inode->osd2.linux2.l_i_uid_high << 16)));
2582 break;
2583 case 'g':
2584 printf("%d", (inode->i_gid |
2585 (inode->osd2.linux2.l_i_gid_high << 16)));
2586 break;
2587 default:
2588 no_inode:
2589 printf("%%I%c", ch);
2590 break;
2595 * This function expands '%dX' expressions
2597 static void expand_dirent_expression(char ch,
2598 struct problem_context *ctx)
2600 struct ext2_dir_entry *dirent;
2601 int len;
2603 if (!ctx || !ctx->dirent)
2604 goto no_dirent;
2606 dirent = ctx->dirent;
2608 switch (ch) {
2609 case 'i':
2610 printf("%u", dirent->inode);
2611 break;
2612 case 'n':
2613 len = dirent->name_len & 0xFF;
2614 if (len > EXT2_NAME_LEN)
2615 len = EXT2_NAME_LEN;
2616 if (len > dirent->rec_len)
2617 len = dirent->rec_len;
2618 safe_print(dirent->name, len);
2619 break;
2620 case 'r':
2621 printf("%u", dirent->rec_len);
2622 break;
2623 case 'l':
2624 printf("%u", dirent->name_len & 0xFF);
2625 break;
2626 case 't':
2627 printf("%u", dirent->name_len >> 8);
2628 break;
2629 default:
2630 no_dirent:
2631 printf("%%D%c", ch);
2632 break;
2636 static void expand_percent_expression(ext2_filsys fs, char ch,
2637 struct problem_context *ctx)
2639 if (!ctx)
2640 goto no_context;
2642 switch (ch) {
2643 case '%':
2644 bb_putchar('%');
2645 break;
2646 case 'b':
2647 printf("%u", ctx->blk);
2648 break;
2649 case 'B':
2650 printf("%"PRIi64, ctx->blkcount);
2651 break;
2652 case 'c':
2653 printf("%u", ctx->blk2);
2654 break;
2655 case 'd':
2656 printf("%u", ctx->dir);
2657 break;
2658 case 'g':
2659 printf("%d", ctx->group);
2660 break;
2661 case 'i':
2662 printf("%u", ctx->ino);
2663 break;
2664 case 'j':
2665 printf("%u", ctx->ino2);
2666 break;
2667 case 'm':
2668 fputs(error_message(ctx->errcode), stdout);
2669 break;
2670 case 'N':
2671 printf("%"PRIi64, ctx->num);
2672 break;
2673 case 'p':
2674 print_pathname(fs, ctx->ino, 0);
2675 break;
2676 case 'P':
2677 print_pathname(fs, ctx->ino2,
2678 ctx->dirent ? ctx->dirent->inode : 0);
2679 break;
2680 case 'q':
2681 print_pathname(fs, ctx->dir, 0);
2682 break;
2683 case 'Q':
2684 print_pathname(fs, ctx->dir, ctx->ino);
2685 break;
2686 case 'S':
2687 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
2688 break;
2689 case 's':
2690 fputs((ctx->str ? ctx->str : "NULL"), stdout);
2691 break;
2692 case 'X':
2693 printf("0x%"PRIi64, ctx->num);
2694 break;
2695 default:
2696 no_context:
2697 printf("%%%c", ch);
2698 break;
2703 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2704 struct problem_context *pctx, int first)
2706 ext2_filsys fs = ctx->fs;
2707 const char * cp;
2708 int i;
2710 e2fsck_clear_progbar(ctx);
2711 for (cp = msg; *cp; cp++) {
2712 if (cp[0] == '@') {
2713 cp++;
2714 expand_at_expression(ctx, *cp, pctx, &first);
2715 } else if (cp[0] == '%' && cp[1] == 'I') {
2716 cp += 2;
2717 expand_inode_expression(*cp, pctx);
2718 } else if (cp[0] == '%' && cp[1] == 'D') {
2719 cp += 2;
2720 expand_dirent_expression(*cp, pctx);
2721 } else if ((cp[0] == '%')) {
2722 cp++;
2723 expand_percent_expression(fs, *cp, pctx);
2724 } else {
2725 for (i=0; cp[i]; i++)
2726 if ((cp[i] == '@') || cp[i] == '%')
2727 break;
2728 printf("%.*s", i, cp);
2729 cp += i-1;
2731 first = 0;
2737 * region.c --- code which manages allocations within a region.
2740 struct region_el {
2741 region_addr_t start;
2742 region_addr_t end;
2743 struct region_el *next;
2746 struct region_struct {
2747 region_addr_t min;
2748 region_addr_t max;
2749 struct region_el *allocated;
2752 static region_t region_create(region_addr_t min, region_addr_t max)
2754 region_t region;
2756 region = xzalloc(sizeof(struct region_struct));
2757 region->min = min;
2758 region->max = max;
2759 return region;
2762 static void region_free(region_t region)
2764 struct region_el *r, *next;
2766 for (r = region->allocated; r; r = next) {
2767 next = r->next;
2768 free(r);
2770 memset(region, 0, sizeof(struct region_struct));
2771 free(region);
2774 static int region_allocate(region_t region, region_addr_t start, int n)
2776 struct region_el *r, *new_region, *prev, *next;
2777 region_addr_t end;
2779 end = start+n;
2780 if ((start < region->min) || (end > region->max))
2781 return -1;
2782 if (n == 0)
2783 return 1;
2786 * Search through the linked list. If we find that it
2787 * conflicts witih something that's already allocated, return
2788 * 1; if we can find an existing region which we can grow, do
2789 * so. Otherwise, stop when we find the appropriate place
2790 * insert a new region element into the linked list.
2792 for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
2793 if (((start >= r->start) && (start < r->end)) ||
2794 ((end > r->start) && (end <= r->end)) ||
2795 ((start <= r->start) && (end >= r->end)))
2796 return 1;
2797 if (end == r->start) {
2798 r->start = start;
2799 return 0;
2801 if (start == r->end) {
2802 if ((next = r->next)) {
2803 if (end > next->start)
2804 return 1;
2805 if (end == next->start) {
2806 r->end = next->end;
2807 r->next = next->next;
2808 free(next);
2809 return 0;
2812 r->end = end;
2813 return 0;
2815 if (start < r->start)
2816 break;
2819 * Insert a new region element structure into the linked list
2821 new_region = xmalloc(sizeof(struct region_el));
2822 new_region->start = start;
2823 new_region->end = start + n;
2824 new_region->next = r;
2825 if (prev)
2826 prev->next = new_region;
2827 else
2828 region->allocated = new_region;
2829 return 0;
2833 * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
2835 * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
2836 * and applies the following tests to each inode:
2838 * - The mode field of the inode must be legal.
2839 * - The size and block count fields of the inode are correct.
2840 * - A data block must not be used by another inode
2842 * Pass 1 also gathers the collects the following information:
2844 * - A bitmap of which inodes are in use. (inode_used_map)
2845 * - A bitmap of which inodes are directories. (inode_dir_map)
2846 * - A bitmap of which inodes are regular files. (inode_reg_map)
2847 * - A bitmap of which inodes have bad fields. (inode_bad_map)
2848 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
2849 * - A bitmap of which blocks are in use. (block_found_map)
2850 * - A bitmap of which blocks are in use by two inodes (block_dup_map)
2851 * - The data blocks of the directory inodes. (dir_map)
2853 * Pass 1 is designed to stash away enough information so that the
2854 * other passes should not need to read in the inode information
2855 * during the normal course of a filesystem check. (Althogh if an
2856 * inconsistency is detected, other passes may need to read in an
2857 * inode to fix it.)
2859 * Note that pass 1B will be invoked if there are any duplicate blocks
2860 * found.
2864 static int process_block(ext2_filsys fs, blk_t *blocknr,
2865 e2_blkcnt_t blockcnt, blk_t ref_blk,
2866 int ref_offset, void *priv_data);
2867 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
2868 e2_blkcnt_t blockcnt, blk_t ref_blk,
2869 int ref_offset, void *priv_data);
2870 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
2871 char *block_buf);
2872 static void mark_table_blocks(e2fsck_t ctx);
2873 static void alloc_imagic_map(e2fsck_t ctx);
2874 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
2875 static void handle_fs_bad_blocks(e2fsck_t ctx);
2876 static void process_inodes(e2fsck_t ctx, char *block_buf);
2877 static int process_inode_cmp(const void *a, const void *b);
2878 static errcode_t scan_callback(ext2_filsys fs,
2879 dgrp_t group, void * priv_data);
2880 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
2881 char *block_buf, int adjust_sign);
2882 /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
2884 static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
2885 struct ext2_inode * inode, int bufsize,
2886 const char *proc);
2888 struct process_block_struct_1 {
2889 ext2_ino_t ino;
2890 unsigned is_dir:1, is_reg:1, clear:1, suppress:1,
2891 fragmented:1, compressed:1, bbcheck:1;
2892 blk_t num_blocks;
2893 blk_t max_blocks;
2894 e2_blkcnt_t last_block;
2895 int num_illegal_blocks;
2896 blk_t previous_block;
2897 struct ext2_inode *inode;
2898 struct problem_context *pctx;
2899 ext2fs_block_bitmap fs_meta_blocks;
2900 e2fsck_t ctx;
2903 struct process_inode_block {
2904 ext2_ino_t ino;
2905 struct ext2_inode inode;
2908 struct scan_callback_struct {
2909 e2fsck_t ctx;
2910 char *block_buf;
2914 * For the inodes to process list.
2916 static struct process_inode_block *inodes_to_process;
2917 static int process_inode_count;
2919 static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
2920 EXT2_MIN_BLOCK_LOG_SIZE + 1];
2923 * Free all memory allocated by pass1 in preparation for restarting
2924 * things.
2926 static void unwind_pass1(void)
2928 ext2fs_free_mem(&inodes_to_process);
2932 * Check to make sure a device inode is real. Returns 1 if the device
2933 * checks out, 0 if not.
2935 * Note: this routine is now also used to check FIFO's and Sockets,
2936 * since they have the same requirement; the i_block fields should be
2937 * zero.
2939 static int
2940 e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
2942 int i;
2945 * If i_blocks is non-zero, or the index flag is set, then
2946 * this is a bogus device/fifo/socket
2948 if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
2949 (inode->i_flags & EXT2_INDEX_FL))
2950 return 0;
2953 * We should be able to do the test below all the time, but
2954 * because the kernel doesn't forcibly clear the device
2955 * inode's additional i_block fields, there are some rare
2956 * occasions when a legitimate device inode will have non-zero
2957 * additional i_block fields. So for now, we only complain
2958 * when the immutable flag is set, which should never happen
2959 * for devices. (And that's when the problem is caused, since
2960 * you can't set or clear immutable flags for devices.) Once
2961 * the kernel has been fixed we can change this...
2963 if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
2964 for (i=4; i < EXT2_N_BLOCKS; i++)
2965 if (inode->i_block[i])
2966 return 0;
2968 return 1;
2972 * Check to make sure a symlink inode is real. Returns 1 if the symlink
2973 * checks out, 0 if not.
2975 static int
2976 e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
2978 unsigned int len;
2979 int i;
2980 blk_t blocks;
2982 if ((inode->i_size_high || inode->i_size == 0) ||
2983 (inode->i_flags & EXT2_INDEX_FL))
2984 return 0;
2986 blocks = ext2fs_inode_data_blocks(fs, inode);
2987 if (blocks) {
2988 if ((inode->i_size >= fs->blocksize) ||
2989 (blocks != fs->blocksize >> 9) ||
2990 (inode->i_block[0] < fs->super->s_first_data_block) ||
2991 (inode->i_block[0] >= fs->super->s_blocks_count))
2992 return 0;
2994 for (i = 1; i < EXT2_N_BLOCKS; i++)
2995 if (inode->i_block[i])
2996 return 0;
2998 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
2999 return 0;
3001 len = strnlen(buf, fs->blocksize);
3002 if (len == fs->blocksize)
3003 return 0;
3004 } else {
3005 if (inode->i_size >= sizeof(inode->i_block))
3006 return 0;
3008 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
3009 if (len == sizeof(inode->i_block))
3010 return 0;
3012 if (len != inode->i_size)
3013 return 0;
3014 return 1;
3018 * If the immutable (or append-only) flag is set on the inode, offer
3019 * to clear it.
3021 #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
3022 static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
3024 if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
3025 return;
3027 if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
3028 return;
3030 pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
3031 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3035 * If device, fifo or socket, check size is zero -- if not offer to
3036 * clear it
3038 static void check_size(e2fsck_t ctx, struct problem_context *pctx)
3040 struct ext2_inode *inode = pctx->inode;
3042 if ((inode->i_size == 0) && (inode->i_size_high == 0))
3043 return;
3045 if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
3046 return;
3048 inode->i_size = 0;
3049 inode->i_size_high = 0;
3050 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3053 static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
3055 struct ext2_super_block *sb = ctx->fs->super;
3056 struct ext2_inode_large *inode;
3057 struct ext2_ext_attr_entry *entry;
3058 char *start, *end;
3059 int storage_size, remain, offs;
3060 int problem = 0;
3062 inode = (struct ext2_inode_large *) pctx->inode;
3063 storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
3064 inode->i_extra_isize;
3065 start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3066 inode->i_extra_isize + sizeof(__u32);
3067 end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
3068 entry = (struct ext2_ext_attr_entry *) start;
3070 /* scan all entry's headers first */
3072 /* take finish entry 0UL into account */
3073 remain = storage_size - sizeof(__u32);
3074 offs = end - start;
3076 while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
3078 /* header eats this space */
3079 remain -= sizeof(struct ext2_ext_attr_entry);
3081 /* is attribute name valid? */
3082 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
3083 pctx->num = entry->e_name_len;
3084 problem = PR_1_ATTR_NAME_LEN;
3085 goto fix;
3088 /* attribute len eats this space */
3089 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
3091 /* check value size */
3092 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
3093 pctx->num = entry->e_value_size;
3094 problem = PR_1_ATTR_VALUE_SIZE;
3095 goto fix;
3098 /* check value placement */
3099 if (entry->e_value_offs +
3100 EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
3101 printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
3102 pctx->num = entry->e_value_offs;
3103 problem = PR_1_ATTR_VALUE_OFFSET;
3104 goto fix;
3107 /* e_value_block must be 0 in inode's ea */
3108 if (entry->e_value_block != 0) {
3109 pctx->num = entry->e_value_block;
3110 problem = PR_1_ATTR_VALUE_BLOCK;
3111 goto fix;
3114 /* e_hash must be 0 in inode's ea */
3115 if (entry->e_hash != 0) {
3116 pctx->num = entry->e_hash;
3117 problem = PR_1_ATTR_HASH;
3118 goto fix;
3121 remain -= entry->e_value_size;
3122 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
3124 entry = EXT2_EXT_ATTR_NEXT(entry);
3126 fix:
3128 * it seems like a corruption. it's very unlikely we could repair
3129 * EA(s) in automatic fashion -bzzz
3131 if (problem == 0 || !fix_problem(ctx, problem, pctx))
3132 return;
3134 /* simple remove all possible EA(s) */
3135 *((__u32 *)start) = 0UL;
3136 e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
3137 EXT2_INODE_SIZE(sb), "pass1");
3140 static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
3142 struct ext2_super_block *sb = ctx->fs->super;
3143 struct ext2_inode_large *inode;
3144 __u32 *eamagic;
3145 int min, max;
3147 inode = (struct ext2_inode_large *) pctx->inode;
3148 if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
3149 /* this isn't large inode. so, nothing to check */
3150 return;
3153 /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
3154 min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
3155 max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
3157 * For now we will allow i_extra_isize to be 0, but really
3158 * implementations should never allow i_extra_isize to be 0
3160 if (inode->i_extra_isize &&
3161 (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
3162 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
3163 return;
3164 inode->i_extra_isize = min;
3165 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
3166 EXT2_INODE_SIZE(sb), "pass1");
3167 return;
3170 eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3171 inode->i_extra_isize);
3172 if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
3173 /* it seems inode has an extended attribute(s) in body */
3174 check_ea_in_inode(ctx, pctx);
3178 static void e2fsck_pass1(e2fsck_t ctx)
3180 int i;
3181 __u64 max_sizes;
3182 ext2_filsys fs = ctx->fs;
3183 ext2_ino_t ino;
3184 struct ext2_inode *inode;
3185 ext2_inode_scan scan;
3186 char *block_buf;
3187 unsigned char frag, fsize;
3188 struct problem_context pctx;
3189 struct scan_callback_struct scan_struct;
3190 struct ext2_super_block *sb = ctx->fs->super;
3191 int imagic_fs;
3192 int busted_fs_time = 0;
3193 int inode_size;
3195 clear_problem_context(&pctx);
3197 if (!(ctx->options & E2F_OPT_PREEN))
3198 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
3200 if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
3201 !(ctx->options & E2F_OPT_NO)) {
3202 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
3203 ctx->dirs_to_hash = 0;
3206 /* Pass 1 */
3208 #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
3210 for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
3211 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
3212 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
3213 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
3214 max_sizes = (max_sizes * (1UL << i)) - 1;
3215 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
3217 #undef EXT2_BPP
3219 imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
3222 * Allocate bitmaps structures
3224 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
3225 &ctx->inode_used_map);
3226 if (pctx.errcode) {
3227 pctx.num = 1;
3228 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3229 ctx->flags |= E2F_FLAG_ABORT;
3230 return;
3232 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3233 _("directory inode map"), &ctx->inode_dir_map);
3234 if (pctx.errcode) {
3235 pctx.num = 2;
3236 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3237 ctx->flags |= E2F_FLAG_ABORT;
3238 return;
3240 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3241 _("regular file inode map"), &ctx->inode_reg_map);
3242 if (pctx.errcode) {
3243 pctx.num = 6;
3244 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3245 ctx->flags |= E2F_FLAG_ABORT;
3246 return;
3248 pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
3249 &ctx->block_found_map);
3250 if (pctx.errcode) {
3251 pctx.num = 1;
3252 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3253 ctx->flags |= E2F_FLAG_ABORT;
3254 return;
3256 pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
3257 &ctx->inode_link_info);
3258 if (pctx.errcode) {
3259 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
3260 ctx->flags |= E2F_FLAG_ABORT;
3261 return;
3263 inode_size = EXT2_INODE_SIZE(fs->super);
3264 inode = (struct ext2_inode *)
3265 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
3267 inodes_to_process = (struct process_inode_block *)
3268 e2fsck_allocate_memory(ctx,
3269 (ctx->process_inode_size *
3270 sizeof(struct process_inode_block)),
3271 "array of inodes to process");
3272 process_inode_count = 0;
3274 pctx.errcode = ext2fs_init_dblist(fs, 0);
3275 if (pctx.errcode) {
3276 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
3277 ctx->flags |= E2F_FLAG_ABORT;
3278 return;
3282 * If the last orphan field is set, clear it, since the pass1
3283 * processing will automatically find and clear the orphans.
3284 * In the future, we may want to try using the last_orphan
3285 * linked list ourselves, but for now, we clear it so that the
3286 * ext3 mount code won't get confused.
3288 if (!(ctx->options & E2F_OPT_READONLY)) {
3289 if (fs->super->s_last_orphan) {
3290 fs->super->s_last_orphan = 0;
3291 ext2fs_mark_super_dirty(fs);
3295 mark_table_blocks(ctx);
3296 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
3297 "block interate buffer");
3298 e2fsck_use_inode_shortcuts(ctx, 1);
3299 ehandler_operation(_("doing inode scan"));
3300 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
3301 &scan);
3302 if (pctx.errcode) {
3303 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3304 ctx->flags |= E2F_FLAG_ABORT;
3305 return;
3307 ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
3308 ctx->stashed_inode = inode;
3309 scan_struct.ctx = ctx;
3310 scan_struct.block_buf = block_buf;
3311 ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
3312 if (ctx->progress)
3313 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
3314 return;
3315 if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
3316 (fs->super->s_mtime < fs->super->s_inodes_count))
3317 busted_fs_time = 1;
3319 while (1) {
3320 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
3321 inode, inode_size);
3322 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3323 return;
3324 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
3325 continue;
3327 if (pctx.errcode) {
3328 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3329 ctx->flags |= E2F_FLAG_ABORT;
3330 return;
3332 if (!ino)
3333 break;
3334 pctx.ino = ino;
3335 pctx.inode = inode;
3336 ctx->stashed_ino = ino;
3337 if (inode->i_links_count) {
3338 pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
3339 ino, inode->i_links_count);
3340 if (pctx.errcode) {
3341 pctx.num = inode->i_links_count;
3342 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
3343 ctx->flags |= E2F_FLAG_ABORT;
3344 return;
3347 if (ino == EXT2_BAD_INO) {
3348 struct process_block_struct_1 pb;
3350 pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
3351 &pb.fs_meta_blocks);
3352 if (pctx.errcode) {
3353 pctx.num = 4;
3354 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3355 ctx->flags |= E2F_FLAG_ABORT;
3356 return;
3358 pb.ino = EXT2_BAD_INO;
3359 pb.num_blocks = pb.last_block = 0;
3360 pb.num_illegal_blocks = 0;
3361 pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
3362 pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
3363 pb.inode = inode;
3364 pb.pctx = &pctx;
3365 pb.ctx = ctx;
3366 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
3367 block_buf, process_bad_block, &pb);
3368 ext2fs_free_block_bitmap(pb.fs_meta_blocks);
3369 if (pctx.errcode) {
3370 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
3371 ctx->flags |= E2F_FLAG_ABORT;
3372 return;
3374 if (pb.bbcheck)
3375 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
3376 ctx->flags |= E2F_FLAG_ABORT;
3377 return;
3379 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3380 clear_problem_context(&pctx);
3381 continue;
3382 } else if (ino == EXT2_ROOT_INO) {
3384 * Make sure the root inode is a directory; if
3385 * not, offer to clear it. It will be
3386 * regnerated in pass #3.
3388 if (!LINUX_S_ISDIR(inode->i_mode)) {
3389 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
3390 inode->i_dtime = time(NULL);
3391 inode->i_links_count = 0;
3392 ext2fs_icount_store(ctx->inode_link_info,
3393 ino, 0);
3394 e2fsck_write_inode(ctx, ino, inode,
3395 "pass1");
3399 * If dtime is set, offer to clear it. mke2fs
3400 * version 0.2b created filesystems with the
3401 * dtime field set for the root and lost+found
3402 * directories. We won't worry about
3403 * /lost+found, since that can be regenerated
3404 * easily. But we will fix the root directory
3405 * as a special case.
3407 if (inode->i_dtime && inode->i_links_count) {
3408 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
3409 inode->i_dtime = 0;
3410 e2fsck_write_inode(ctx, ino, inode,
3411 "pass1");
3414 } else if (ino == EXT2_JOURNAL_INO) {
3415 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3416 if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
3417 if (!LINUX_S_ISREG(inode->i_mode) &&
3418 fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
3419 &pctx)) {
3420 inode->i_mode = LINUX_S_IFREG;
3421 e2fsck_write_inode(ctx, ino, inode,
3422 "pass1");
3424 check_blocks(ctx, &pctx, block_buf);
3425 continue;
3427 if ((inode->i_links_count || inode->i_blocks ||
3428 inode->i_blocks || inode->i_block[0]) &&
3429 fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
3430 &pctx)) {
3431 memset(inode, 0, inode_size);
3432 ext2fs_icount_store(ctx->inode_link_info,
3433 ino, 0);
3434 e2fsck_write_inode_full(ctx, ino, inode,
3435 inode_size, "pass1");
3437 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
3438 int problem = 0;
3440 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3441 if (ino == EXT2_BOOT_LOADER_INO) {
3442 if (LINUX_S_ISDIR(inode->i_mode))
3443 problem = PR_1_RESERVED_BAD_MODE;
3444 } else if (ino == EXT2_RESIZE_INO) {
3445 if (inode->i_mode &&
3446 !LINUX_S_ISREG(inode->i_mode))
3447 problem = PR_1_RESERVED_BAD_MODE;
3448 } else {
3449 if (inode->i_mode != 0)
3450 problem = PR_1_RESERVED_BAD_MODE;
3452 if (problem) {
3453 if (fix_problem(ctx, problem, &pctx)) {
3454 inode->i_mode = 0;
3455 e2fsck_write_inode(ctx, ino, inode,
3456 "pass1");
3459 check_blocks(ctx, &pctx, block_buf);
3460 continue;
3463 * Check for inodes who might have been part of the
3464 * orphaned list linked list. They should have gotten
3465 * dealt with by now, unless the list had somehow been
3466 * corrupted.
3468 * FIXME: In the future, inodes which are still in use
3469 * (and which are therefore) pending truncation should
3470 * be handled specially. Right now we just clear the
3471 * dtime field, and the normal e2fsck handling of
3472 * inodes where i_size and the inode blocks are
3473 * inconsistent is to fix i_size, instead of releasing
3474 * the extra blocks. This won't catch the inodes that
3475 * was at the end of the orphan list, but it's better
3476 * than nothing. The right answer is that there
3477 * shouldn't be any bugs in the orphan list handling. :-)
3479 if (inode->i_dtime && !busted_fs_time &&
3480 inode->i_dtime < ctx->fs->super->s_inodes_count) {
3481 if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
3482 inode->i_dtime = inode->i_links_count ?
3483 0 : time(NULL);
3484 e2fsck_write_inode(ctx, ino, inode,
3485 "pass1");
3490 * This code assumes that deleted inodes have
3491 * i_links_count set to 0.
3493 if (!inode->i_links_count) {
3494 if (!inode->i_dtime && inode->i_mode) {
3495 if (fix_problem(ctx,
3496 PR_1_ZERO_DTIME, &pctx)) {
3497 inode->i_dtime = time(NULL);
3498 e2fsck_write_inode(ctx, ino, inode,
3499 "pass1");
3502 continue;
3505 * n.b. 0.3c ext2fs code didn't clear i_links_count for
3506 * deleted files. Oops.
3508 * Since all new ext2 implementations get this right,
3509 * we now assume that the case of non-zero
3510 * i_links_count and non-zero dtime means that we
3511 * should keep the file, not delete it.
3514 if (inode->i_dtime) {
3515 if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
3516 inode->i_dtime = 0;
3517 e2fsck_write_inode(ctx, ino, inode, "pass1");
3521 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3522 switch (fs->super->s_creator_os) {
3523 case EXT2_OS_LINUX:
3524 frag = inode->osd2.linux2.l_i_frag;
3525 fsize = inode->osd2.linux2.l_i_fsize;
3526 break;
3527 case EXT2_OS_HURD:
3528 frag = inode->osd2.hurd2.h_i_frag;
3529 fsize = inode->osd2.hurd2.h_i_fsize;
3530 break;
3531 case EXT2_OS_MASIX:
3532 frag = inode->osd2.masix2.m_i_frag;
3533 fsize = inode->osd2.masix2.m_i_fsize;
3534 break;
3535 default:
3536 frag = fsize = 0;
3539 if (inode->i_faddr || frag || fsize ||
3540 (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
3541 mark_inode_bad(ctx, ino);
3542 if (inode->i_flags & EXT2_IMAGIC_FL) {
3543 if (imagic_fs) {
3544 if (!ctx->inode_imagic_map)
3545 alloc_imagic_map(ctx);
3546 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
3547 ino);
3548 } else {
3549 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
3550 inode->i_flags &= ~EXT2_IMAGIC_FL;
3551 e2fsck_write_inode(ctx, ino,
3552 inode, "pass1");
3557 check_inode_extra_space(ctx, &pctx);
3559 if (LINUX_S_ISDIR(inode->i_mode)) {
3560 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
3561 e2fsck_add_dir_info(ctx, ino, 0);
3562 ctx->fs_directory_count++;
3563 } else if (LINUX_S_ISREG (inode->i_mode)) {
3564 ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
3565 ctx->fs_regular_count++;
3566 } else if (LINUX_S_ISCHR (inode->i_mode) &&
3567 e2fsck_pass1_check_device_inode(fs, inode)) {
3568 check_immutable(ctx, &pctx);
3569 check_size(ctx, &pctx);
3570 ctx->fs_chardev_count++;
3571 } else if (LINUX_S_ISBLK (inode->i_mode) &&
3572 e2fsck_pass1_check_device_inode(fs, inode)) {
3573 check_immutable(ctx, &pctx);
3574 check_size(ctx, &pctx);
3575 ctx->fs_blockdev_count++;
3576 } else if (LINUX_S_ISLNK (inode->i_mode) &&
3577 e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
3578 check_immutable(ctx, &pctx);
3579 ctx->fs_symlinks_count++;
3580 if (ext2fs_inode_data_blocks(fs, inode) == 0) {
3581 ctx->fs_fast_symlinks_count++;
3582 check_blocks(ctx, &pctx, block_buf);
3583 continue;
3586 else if (LINUX_S_ISFIFO (inode->i_mode) &&
3587 e2fsck_pass1_check_device_inode(fs, inode)) {
3588 check_immutable(ctx, &pctx);
3589 check_size(ctx, &pctx);
3590 ctx->fs_fifo_count++;
3591 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
3592 e2fsck_pass1_check_device_inode(fs, inode)) {
3593 check_immutable(ctx, &pctx);
3594 check_size(ctx, &pctx);
3595 ctx->fs_sockets_count++;
3596 } else
3597 mark_inode_bad(ctx, ino);
3598 if (inode->i_block[EXT2_IND_BLOCK])
3599 ctx->fs_ind_count++;
3600 if (inode->i_block[EXT2_DIND_BLOCK])
3601 ctx->fs_dind_count++;
3602 if (inode->i_block[EXT2_TIND_BLOCK])
3603 ctx->fs_tind_count++;
3604 if (inode->i_block[EXT2_IND_BLOCK] ||
3605 inode->i_block[EXT2_DIND_BLOCK] ||
3606 inode->i_block[EXT2_TIND_BLOCK] ||
3607 inode->i_file_acl) {
3608 inodes_to_process[process_inode_count].ino = ino;
3609 inodes_to_process[process_inode_count].inode = *inode;
3610 process_inode_count++;
3611 } else
3612 check_blocks(ctx, &pctx, block_buf);
3614 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3615 return;
3617 if (process_inode_count >= ctx->process_inode_size) {
3618 process_inodes(ctx, block_buf);
3620 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3621 return;
3624 process_inodes(ctx, block_buf);
3625 ext2fs_close_inode_scan(scan);
3626 ehandler_operation(0);
3629 * If any extended attribute blocks' reference counts need to
3630 * be adjusted, either up (ctx->refcount_extra), or down
3631 * (ctx->refcount), then fix them.
3633 if (ctx->refcount) {
3634 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
3635 ea_refcount_free(ctx->refcount);
3636 ctx->refcount = 0;
3638 if (ctx->refcount_extra) {
3639 adjust_extattr_refcount(ctx, ctx->refcount_extra,
3640 block_buf, +1);
3641 ea_refcount_free(ctx->refcount_extra);
3642 ctx->refcount_extra = 0;
3645 if (ctx->invalid_bitmaps)
3646 handle_fs_bad_blocks(ctx);
3648 /* We don't need the block_ea_map any more */
3649 ext2fs_free_block_bitmap(ctx->block_ea_map);
3650 ctx->block_ea_map = 0;
3652 if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
3653 ext2fs_block_bitmap save_bmap;
3655 save_bmap = fs->block_map;
3656 fs->block_map = ctx->block_found_map;
3657 clear_problem_context(&pctx);
3658 pctx.errcode = ext2fs_create_resize_inode(fs);
3659 if (pctx.errcode) {
3660 fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
3661 /* Should never get here */
3662 ctx->flags |= E2F_FLAG_ABORT;
3663 return;
3665 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
3666 "recreate inode");
3667 inode->i_mtime = time(NULL);
3668 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
3669 "recreate inode");
3670 fs->block_map = save_bmap;
3671 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
3674 if (ctx->flags & E2F_FLAG_RESTART) {
3676 * Only the master copy of the superblock and block
3677 * group descriptors are going to be written during a
3678 * restart, so set the superblock to be used to be the
3679 * master superblock.
3681 ctx->use_superblock = 0;
3682 unwind_pass1();
3683 goto endit;
3686 if (ctx->block_dup_map) {
3687 if (ctx->options & E2F_OPT_PREEN) {
3688 clear_problem_context(&pctx);
3689 fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
3691 e2fsck_pass1_dupblocks(ctx, block_buf);
3693 ext2fs_free_mem(&inodes_to_process);
3694 endit:
3695 e2fsck_use_inode_shortcuts(ctx, 0);
3697 ext2fs_free_mem(&block_buf);
3698 ext2fs_free_mem(&inode);
3702 * When the inode_scan routines call this callback at the end of the
3703 * glock group, call process_inodes.
3705 static errcode_t scan_callback(ext2_filsys fs,
3706 dgrp_t group, void * priv_data)
3708 struct scan_callback_struct *scan_struct;
3709 e2fsck_t ctx;
3711 scan_struct = (struct scan_callback_struct *) priv_data;
3712 ctx = scan_struct->ctx;
3714 process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
3716 if (ctx->progress)
3717 if ((ctx->progress)(ctx, 1, group+1,
3718 ctx->fs->group_desc_count))
3719 return EXT2_ET_CANCEL_REQUESTED;
3721 return 0;
3725 * Process the inodes in the "inodes to process" list.
3727 static void process_inodes(e2fsck_t ctx, char *block_buf)
3729 int i;
3730 struct ext2_inode *old_stashed_inode;
3731 ext2_ino_t old_stashed_ino;
3732 const char *old_operation;
3733 char buf[80];
3734 struct problem_context pctx;
3736 /* begin process_inodes */
3737 if (process_inode_count == 0)
3738 return;
3739 old_operation = ehandler_operation(0);
3740 old_stashed_inode = ctx->stashed_inode;
3741 old_stashed_ino = ctx->stashed_ino;
3742 qsort(inodes_to_process, process_inode_count,
3743 sizeof(struct process_inode_block), process_inode_cmp);
3744 clear_problem_context(&pctx);
3745 for (i=0; i < process_inode_count; i++) {
3746 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
3747 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
3748 sprintf(buf, _("reading indirect blocks of inode %u"),
3749 pctx.ino);
3750 ehandler_operation(buf);
3751 check_blocks(ctx, &pctx, block_buf);
3752 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3753 break;
3755 ctx->stashed_inode = old_stashed_inode;
3756 ctx->stashed_ino = old_stashed_ino;
3757 process_inode_count = 0;
3758 /* end process inodes */
3760 ehandler_operation(old_operation);
3763 static int process_inode_cmp(const void *a, const void *b)
3765 const struct process_inode_block *ib_a =
3766 (const struct process_inode_block *) a;
3767 const struct process_inode_block *ib_b =
3768 (const struct process_inode_block *) b;
3769 int ret;
3771 ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
3772 ib_b->inode.i_block[EXT2_IND_BLOCK]);
3773 if (ret == 0)
3774 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
3775 return ret;
3779 * Mark an inode as being bad in some what
3781 static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
3783 struct problem_context pctx;
3785 if (!ctx->inode_bad_map) {
3786 clear_problem_context(&pctx);
3788 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3789 _("bad inode map"), &ctx->inode_bad_map);
3790 if (pctx.errcode) {
3791 pctx.num = 3;
3792 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3793 /* Should never get here */
3794 ctx->flags |= E2F_FLAG_ABORT;
3795 return;
3798 ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
3803 * This procedure will allocate the inode imagic table
3805 static void alloc_imagic_map(e2fsck_t ctx)
3807 struct problem_context pctx;
3809 clear_problem_context(&pctx);
3810 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3811 _("imagic inode map"),
3812 &ctx->inode_imagic_map);
3813 if (pctx.errcode) {
3814 pctx.num = 5;
3815 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3816 /* Should never get here */
3817 ctx->flags |= E2F_FLAG_ABORT;
3818 return;
3823 * Marks a block as in use, setting the dup_map if it's been set
3824 * already. Called by process_block and process_bad_block.
3826 * WARNING: Assumes checks have already been done to make sure block
3827 * is valid. This is true in both process_block and process_bad_block.
3829 static void mark_block_used(e2fsck_t ctx, blk_t block)
3831 struct problem_context pctx;
3833 clear_problem_context(&pctx);
3835 if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
3836 if (!ctx->block_dup_map) {
3837 pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
3838 _("multiply claimed block map"),
3839 &ctx->block_dup_map);
3840 if (pctx.errcode) {
3841 pctx.num = 3;
3842 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
3843 &pctx);
3844 /* Should never get here */
3845 ctx->flags |= E2F_FLAG_ABORT;
3846 return;
3849 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
3850 } else {
3851 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
3856 * Adjust the extended attribute block's reference counts at the end
3857 * of pass 1, either by subtracting out references for EA blocks that
3858 * are still referenced in ctx->refcount, or by adding references for
3859 * EA blocks that had extra references as accounted for in
3860 * ctx->refcount_extra.
3862 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3863 char *block_buf, int adjust_sign)
3865 struct ext2_ext_attr_header *header;
3866 struct problem_context pctx;
3867 ext2_filsys fs = ctx->fs;
3868 blk_t blk;
3869 __u32 should_be;
3870 int count;
3872 clear_problem_context(&pctx);
3874 ea_refcount_intr_begin(refcount);
3875 while (1) {
3876 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
3877 break;
3878 pctx.blk = blk;
3879 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3880 if (pctx.errcode) {
3881 fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
3882 return;
3884 header = (struct ext2_ext_attr_header *) block_buf;
3885 pctx.blkcount = header->h_refcount;
3886 should_be = header->h_refcount + adjust_sign * count;
3887 pctx.num = should_be;
3888 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
3889 header->h_refcount = should_be;
3890 pctx.errcode = ext2fs_write_ext_attr(fs, blk,
3891 block_buf);
3892 if (pctx.errcode) {
3893 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
3894 continue;
3901 * Handle processing the extended attribute blocks
3903 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
3904 char *block_buf)
3906 ext2_filsys fs = ctx->fs;
3907 ext2_ino_t ino = pctx->ino;
3908 struct ext2_inode *inode = pctx->inode;
3909 blk_t blk;
3910 char * end;
3911 struct ext2_ext_attr_header *header;
3912 struct ext2_ext_attr_entry *entry;
3913 int count;
3914 region_t region;
3916 blk = inode->i_file_acl;
3917 if (blk == 0)
3918 return 0;
3921 * If the Extended attribute flag isn't set, then a non-zero
3922 * file acl means that the inode is corrupted.
3924 * Or if the extended attribute block is an invalid block,
3925 * then the inode is also corrupted.
3927 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
3928 (blk < fs->super->s_first_data_block) ||
3929 (blk >= fs->super->s_blocks_count)) {
3930 mark_inode_bad(ctx, ino);
3931 return 0;
3934 /* If ea bitmap hasn't been allocated, create it */
3935 if (!ctx->block_ea_map) {
3936 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
3937 _("ext attr block map"),
3938 &ctx->block_ea_map);
3939 if (pctx->errcode) {
3940 pctx->num = 2;
3941 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
3942 ctx->flags |= E2F_FLAG_ABORT;
3943 return 0;
3947 /* Create the EA refcount structure if necessary */
3948 if (!ctx->refcount) {
3949 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
3950 if (pctx->errcode) {
3951 pctx->num = 1;
3952 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3953 ctx->flags |= E2F_FLAG_ABORT;
3954 return 0;
3958 /* Have we seen this EA block before? */
3959 if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
3960 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
3961 return 1;
3962 /* Ooops, this EA was referenced more than it stated */
3963 if (!ctx->refcount_extra) {
3964 pctx->errcode = ea_refcount_create(0,
3965 &ctx->refcount_extra);
3966 if (pctx->errcode) {
3967 pctx->num = 2;
3968 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3969 ctx->flags |= E2F_FLAG_ABORT;
3970 return 0;
3973 ea_refcount_increment(ctx->refcount_extra, blk, 0);
3974 return 1;
3978 * OK, we haven't seen this EA block yet. So we need to
3979 * validate it
3981 pctx->blk = blk;
3982 pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3983 if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
3984 goto clear_extattr;
3985 header = (struct ext2_ext_attr_header *) block_buf;
3986 pctx->blk = inode->i_file_acl;
3987 if (((ctx->ext_attr_ver == 1) &&
3988 (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
3989 ((ctx->ext_attr_ver == 2) &&
3990 (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
3991 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
3992 goto clear_extattr;
3995 if (header->h_blocks != 1) {
3996 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
3997 goto clear_extattr;
4000 region = region_create(0, fs->blocksize);
4001 if (!region) {
4002 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
4003 ctx->flags |= E2F_FLAG_ABORT;
4004 return 0;
4006 if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
4007 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4008 goto clear_extattr;
4011 entry = (struct ext2_ext_attr_entry *)(header+1);
4012 end = block_buf + fs->blocksize;
4013 while ((char *)entry < end && *(__u32 *)entry) {
4014 if (region_allocate(region, (char *)entry - (char *)header,
4015 EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
4016 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4017 goto clear_extattr;
4019 if ((ctx->ext_attr_ver == 1 &&
4020 (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
4021 (ctx->ext_attr_ver == 2 &&
4022 entry->e_name_index == 0)) {
4023 if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
4024 goto clear_extattr;
4026 if (entry->e_value_block != 0) {
4027 if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
4028 goto clear_extattr;
4030 if (entry->e_value_size &&
4031 region_allocate(region, entry->e_value_offs,
4032 EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
4033 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4034 goto clear_extattr;
4036 entry = EXT2_EXT_ATTR_NEXT(entry);
4038 if (region_allocate(region, (char *)entry - (char *)header, 4)) {
4039 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4040 goto clear_extattr;
4042 region_free(region);
4044 count = header->h_refcount - 1;
4045 if (count)
4046 ea_refcount_store(ctx->refcount, blk, count);
4047 mark_block_used(ctx, blk);
4048 ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
4050 return 1;
4052 clear_extattr:
4053 inode->i_file_acl = 0;
4054 e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
4055 return 0;
4058 /* Returns 1 if bad htree, 0 if OK */
4059 static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
4060 ext2_ino_t ino FSCK_ATTR((unused)),
4061 struct ext2_inode *inode,
4062 char *block_buf)
4064 struct ext2_dx_root_info *root;
4065 ext2_filsys fs = ctx->fs;
4066 errcode_t retval;
4067 blk_t blk;
4069 if ((!LINUX_S_ISDIR(inode->i_mode) &&
4070 fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
4071 (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4072 fix_problem(ctx, PR_1_HTREE_SET, pctx)))
4073 return 1;
4075 blk = inode->i_block[0];
4076 if (((blk == 0) ||
4077 (blk < fs->super->s_first_data_block) ||
4078 (blk >= fs->super->s_blocks_count)) &&
4079 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4080 return 1;
4082 retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
4083 if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4084 return 1;
4086 /* XXX should check that beginning matches a directory */
4087 root = (struct ext2_dx_root_info *) (block_buf + 24);
4089 if ((root->reserved_zero || root->info_length < 8) &&
4090 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4091 return 1;
4093 pctx->num = root->hash_version;
4094 if ((root->hash_version != EXT2_HASH_LEGACY) &&
4095 (root->hash_version != EXT2_HASH_HALF_MD4) &&
4096 (root->hash_version != EXT2_HASH_TEA) &&
4097 fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
4098 return 1;
4100 if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
4101 fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
4102 return 1;
4104 pctx->num = root->indirect_levels;
4105 if ((root->indirect_levels > 1) &&
4106 fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
4107 return 1;
4109 return 0;
4113 * This subroutine is called on each inode to account for all of the
4114 * blocks used by that inode.
4116 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4117 char *block_buf)
4119 ext2_filsys fs = ctx->fs;
4120 struct process_block_struct_1 pb;
4121 ext2_ino_t ino = pctx->ino;
4122 struct ext2_inode *inode = pctx->inode;
4123 int bad_size = 0;
4124 int dirty_inode = 0;
4125 __u64 size;
4127 pb.ino = ino;
4128 pb.num_blocks = 0;
4129 pb.last_block = -1;
4130 pb.num_illegal_blocks = 0;
4131 pb.suppress = 0; pb.clear = 0;
4132 pb.fragmented = 0;
4133 pb.compressed = 0;
4134 pb.previous_block = 0;
4135 pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
4136 pb.is_reg = LINUX_S_ISREG(inode->i_mode);
4137 pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
4138 pb.inode = inode;
4139 pb.pctx = pctx;
4140 pb.ctx = ctx;
4141 pctx->ino = ino;
4142 pctx->errcode = 0;
4144 if (inode->i_flags & EXT2_COMPRBLK_FL) {
4145 if (fs->super->s_feature_incompat &
4146 EXT2_FEATURE_INCOMPAT_COMPRESSION)
4147 pb.compressed = 1;
4148 else {
4149 if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
4150 inode->i_flags &= ~EXT2_COMPRBLK_FL;
4151 dirty_inode++;
4156 if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
4157 pb.num_blocks++;
4159 if (ext2fs_inode_has_valid_blocks(inode))
4160 pctx->errcode = ext2fs_block_iterate2(fs, ino,
4161 pb.is_dir ? BLOCK_FLAG_HOLE : 0,
4162 block_buf, process_block, &pb);
4163 end_problem_latch(ctx, PR_LATCH_BLOCK);
4164 end_problem_latch(ctx, PR_LATCH_TOOBIG);
4165 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4166 goto out;
4167 if (pctx->errcode)
4168 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
4170 if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
4171 ctx->fs_fragmented++;
4173 if (pb.clear) {
4174 inode->i_links_count = 0;
4175 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4176 inode->i_dtime = time(NULL);
4177 dirty_inode++;
4178 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4179 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4180 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4182 * The inode was probably partially accounted for
4183 * before processing was aborted, so we need to
4184 * restart the pass 1 scan.
4186 ctx->flags |= E2F_FLAG_RESTART;
4187 goto out;
4190 if (inode->i_flags & EXT2_INDEX_FL) {
4191 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
4192 inode->i_flags &= ~EXT2_INDEX_FL;
4193 dirty_inode++;
4194 } else {
4195 #ifdef ENABLE_HTREE
4196 e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
4197 #endif
4200 if (ctx->dirs_to_hash && pb.is_dir &&
4201 !(inode->i_flags & EXT2_INDEX_FL) &&
4202 ((inode->i_size / fs->blocksize) >= 3))
4203 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
4205 if (!pb.num_blocks && pb.is_dir) {
4206 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
4207 inode->i_links_count = 0;
4208 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4209 inode->i_dtime = time(NULL);
4210 dirty_inode++;
4211 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4212 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4213 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4214 ctx->fs_directory_count--;
4215 goto out;
4219 pb.num_blocks *= (fs->blocksize / 512);
4221 if (pb.is_dir) {
4222 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
4223 if (nblock > (pb.last_block + 1))
4224 bad_size = 1;
4225 else if (nblock < (pb.last_block + 1)) {
4226 if (((pb.last_block + 1) - nblock) >
4227 fs->super->s_prealloc_dir_blocks)
4228 bad_size = 2;
4230 } else {
4231 size = EXT2_I_SIZE(inode);
4232 if ((pb.last_block >= 0) &&
4233 (size < (__u64) pb.last_block * fs->blocksize))
4234 bad_size = 3;
4235 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
4236 bad_size = 4;
4238 /* i_size for symlinks is checked elsewhere */
4239 if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
4240 pctx->num = (pb.last_block+1) * fs->blocksize;
4241 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
4242 inode->i_size = pctx->num;
4243 if (!LINUX_S_ISDIR(inode->i_mode))
4244 inode->i_size_high = pctx->num >> 32;
4245 dirty_inode++;
4247 pctx->num = 0;
4249 if (LINUX_S_ISREG(inode->i_mode) &&
4250 (inode->i_size_high || inode->i_size & 0x80000000UL))
4251 ctx->large_files++;
4252 if (pb.num_blocks != inode->i_blocks) {
4253 pctx->num = pb.num_blocks;
4254 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
4255 inode->i_blocks = pb.num_blocks;
4256 dirty_inode++;
4258 pctx->num = 0;
4260 out:
4261 if (dirty_inode)
4262 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
4267 * This is a helper function for check_blocks().
4269 static int process_block(ext2_filsys fs,
4270 blk_t *block_nr,
4271 e2_blkcnt_t blockcnt,
4272 blk_t ref_block FSCK_ATTR((unused)),
4273 int ref_offset FSCK_ATTR((unused)),
4274 void *priv_data)
4276 struct process_block_struct_1 *p;
4277 struct problem_context *pctx;
4278 blk_t blk = *block_nr;
4279 int ret_code = 0;
4280 int problem = 0;
4281 e2fsck_t ctx;
4283 p = (struct process_block_struct_1 *) priv_data;
4284 pctx = p->pctx;
4285 ctx = p->ctx;
4287 if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
4288 /* todo: Check that the comprblk_fl is high, that the
4289 blkaddr pattern looks right (all non-holes up to
4290 first EXT2FS_COMPRESSED_BLKADDR, then all
4291 EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
4292 that the feature_incompat bit is high, and that the
4293 inode is a regular file. If we're doing a "full
4294 check" (a concept introduced to e2fsck by e2compr,
4295 meaning that we look at data blocks as well as
4296 metadata) then call some library routine that
4297 checks the compressed data. I'll have to think
4298 about this, because one particularly important
4299 problem to be able to fix is to recalculate the
4300 cluster size if necessary. I think that perhaps
4301 we'd better do most/all e2compr-specific checks
4302 separately, after the non-e2compr checks. If not
4303 doing a full check, it may be useful to test that
4304 the personality is linux; e.g. if it isn't then
4305 perhaps this really is just an illegal block. */
4306 return 0;
4309 if (blk == 0) {
4310 if (p->is_dir == 0) {
4312 * Should never happen, since only directories
4313 * get called with BLOCK_FLAG_HOLE
4315 #ifdef DEBUG_E2FSCK
4316 printf("process_block() called with blk == 0, "
4317 "blockcnt=%d, inode %lu???\n",
4318 blockcnt, p->ino);
4319 #endif
4320 return 0;
4322 if (blockcnt < 0)
4323 return 0;
4324 if (blockcnt * fs->blocksize < p->inode->i_size) {
4325 goto mark_dir;
4327 return 0;
4331 * Simplistic fragmentation check. We merely require that the
4332 * file be contiguous. (Which can never be true for really
4333 * big files that are greater than a block group.)
4335 if (!HOLE_BLKADDR(p->previous_block)) {
4336 if (p->previous_block+1 != blk)
4337 p->fragmented = 1;
4339 p->previous_block = blk;
4341 if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
4342 problem = PR_1_TOOBIG_DIR;
4343 if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
4344 problem = PR_1_TOOBIG_REG;
4345 if (!p->is_dir && !p->is_reg && blockcnt > 0)
4346 problem = PR_1_TOOBIG_SYMLINK;
4348 if (blk < fs->super->s_first_data_block ||
4349 blk >= fs->super->s_blocks_count)
4350 problem = PR_1_ILLEGAL_BLOCK_NUM;
4352 if (problem) {
4353 p->num_illegal_blocks++;
4354 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
4355 if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
4356 p->clear = 1;
4357 return BLOCK_ABORT;
4359 if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
4360 p->suppress = 1;
4361 set_latch_flags(PR_LATCH_BLOCK,
4362 PRL_SUPPRESS, 0);
4365 pctx->blk = blk;
4366 pctx->blkcount = blockcnt;
4367 if (fix_problem(ctx, problem, pctx)) {
4368 blk = *block_nr = 0;
4369 ret_code = BLOCK_CHANGED;
4370 goto mark_dir;
4371 } else
4372 return 0;
4375 if (p->ino == EXT2_RESIZE_INO) {
4377 * The resize inode has already be sanity checked
4378 * during pass #0 (the superblock checks). All we
4379 * have to do is mark the double indirect block as
4380 * being in use; all of the other blocks are handled
4381 * by mark_table_blocks()).
4383 if (blockcnt == BLOCK_COUNT_DIND)
4384 mark_block_used(ctx, blk);
4385 } else
4386 mark_block_used(ctx, blk);
4387 p->num_blocks++;
4388 if (blockcnt >= 0)
4389 p->last_block = blockcnt;
4390 mark_dir:
4391 if (p->is_dir && (blockcnt >= 0)) {
4392 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
4393 blk, blockcnt);
4394 if (pctx->errcode) {
4395 pctx->blk = blk;
4396 pctx->num = blockcnt;
4397 fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
4398 /* Should never get here */
4399 ctx->flags |= E2F_FLAG_ABORT;
4400 return BLOCK_ABORT;
4403 return ret_code;
4406 static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
4407 blk_t *block_nr,
4408 e2_blkcnt_t blockcnt,
4409 blk_t ref_block FSCK_ATTR((unused)),
4410 int ref_offset FSCK_ATTR((unused)),
4411 void *priv_data EXT2FS_ATTR((unused)))
4414 * Note: This function processes blocks for the bad blocks
4415 * inode, which is never compressed. So we don't use HOLE_BLKADDR().
4418 printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
4419 return BLOCK_ERROR;
4423 * This routine gets called at the end of pass 1 if bad blocks are
4424 * detected in the superblock, group descriptors, inode_bitmaps, or
4425 * block bitmaps. At this point, all of the blocks have been mapped
4426 * out, so we can try to allocate new block(s) to replace the bad
4427 * blocks.
4429 static void handle_fs_bad_blocks(e2fsck_t ctx EXT2FS_ATTR((unused)))
4431 printf("Bad blocks detected on your filesystem\n"
4432 "You should get your data off as the device will soon die\n");
4436 * This routine marks all blocks which are used by the superblock,
4437 * group descriptors, inode bitmaps, and block bitmaps.
4439 static void mark_table_blocks(e2fsck_t ctx)
4441 ext2_filsys fs = ctx->fs;
4442 blk_t block, b;
4443 dgrp_t i;
4444 int j;
4445 struct problem_context pctx;
4447 clear_problem_context(&pctx);
4449 block = fs->super->s_first_data_block;
4450 for (i = 0; i < fs->group_desc_count; i++) {
4451 pctx.group = i;
4453 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
4456 * Mark the blocks used for the inode table
4458 if (fs->group_desc[i].bg_inode_table) {
4459 for (j = 0, b = fs->group_desc[i].bg_inode_table;
4460 j < fs->inode_blocks_per_group;
4461 j++, b++) {
4462 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4463 b)) {
4464 pctx.blk = b;
4465 if (fix_problem(ctx,
4466 PR_1_ITABLE_CONFLICT, &pctx)) {
4467 ctx->invalid_inode_table_flag[i]++;
4468 ctx->invalid_bitmaps++;
4470 } else {
4471 ext2fs_mark_block_bitmap(ctx->block_found_map, b);
4477 * Mark block used for the block bitmap
4479 if (fs->group_desc[i].bg_block_bitmap) {
4480 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4481 fs->group_desc[i].bg_block_bitmap)) {
4482 pctx.blk = fs->group_desc[i].bg_block_bitmap;
4483 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
4484 ctx->invalid_block_bitmap_flag[i]++;
4485 ctx->invalid_bitmaps++;
4487 } else {
4488 ext2fs_mark_block_bitmap(ctx->block_found_map,
4489 fs->group_desc[i].bg_block_bitmap);
4493 * Mark block used for the inode bitmap
4495 if (fs->group_desc[i].bg_inode_bitmap) {
4496 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4497 fs->group_desc[i].bg_inode_bitmap)) {
4498 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
4499 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
4500 ctx->invalid_inode_bitmap_flag[i]++;
4501 ctx->invalid_bitmaps++;
4503 } else {
4504 ext2fs_mark_block_bitmap(ctx->block_found_map,
4505 fs->group_desc[i].bg_inode_bitmap);
4508 block += fs->super->s_blocks_per_group;
4513 * Thes subroutines short circuits ext2fs_get_blocks and
4514 * ext2fs_check_directory; we use them since we already have the inode
4515 * structure, so there's no point in letting the ext2fs library read
4516 * the inode again.
4518 static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
4519 blk_t *blocks)
4521 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4522 int i;
4524 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4525 return EXT2_ET_CALLBACK_NOTHANDLED;
4527 for (i=0; i < EXT2_N_BLOCKS; i++)
4528 blocks[i] = ctx->stashed_inode->i_block[i];
4529 return 0;
4532 static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
4533 struct ext2_inode *inode)
4535 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4537 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4538 return EXT2_ET_CALLBACK_NOTHANDLED;
4539 *inode = *ctx->stashed_inode;
4540 return 0;
4543 static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
4544 struct ext2_inode *inode)
4546 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4548 if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
4549 *ctx->stashed_inode = *inode;
4550 return EXT2_ET_CALLBACK_NOTHANDLED;
4553 static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
4555 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4557 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4558 return EXT2_ET_CALLBACK_NOTHANDLED;
4560 if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
4561 return EXT2_ET_NO_DIRECTORY;
4562 return 0;
4565 void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int fl_bool)
4567 ext2_filsys fs = ctx->fs;
4569 if (fl_bool) {
4570 fs->get_blocks = pass1_get_blocks;
4571 fs->check_directory = pass1_check_directory;
4572 fs->read_inode = pass1_read_inode;
4573 fs->write_inode = pass1_write_inode;
4574 ctx->stashed_ino = 0;
4575 } else {
4576 fs->get_blocks = 0;
4577 fs->check_directory = 0;
4578 fs->read_inode = 0;
4579 fs->write_inode = 0;
4584 * pass1b.c --- Pass #1b of e2fsck
4586 * This file contains pass1B, pass1C, and pass1D of e2fsck. They are
4587 * only invoked if pass 1 discovered blocks which are in use by more
4588 * than one inode.
4590 * Pass1B scans the data blocks of all the inodes again, generating a
4591 * complete list of duplicate blocks and which inodes have claimed
4592 * them.
4594 * Pass1C does a tree-traversal of the filesystem, to determine the
4595 * parent directories of these inodes. This step is necessary so that
4596 * e2fsck can print out the pathnames of affected inodes.
4598 * Pass1D is a reconciliation pass. For each inode with duplicate
4599 * blocks, the user is prompted if s/he would like to clone the file
4600 * (so that the file gets a fresh copy of the duplicated blocks) or
4601 * simply to delete the file.
4606 /* Needed for architectures where sizeof(int) != sizeof(void *) */
4607 #define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val))
4608 #define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr))
4610 /* Define an extension to the ext2 library's block count information */
4611 #define BLOCK_COUNT_EXTATTR (-5)
4613 struct block_el {
4614 blk_t block;
4615 struct block_el *next;
4618 struct inode_el {
4619 ext2_ino_t inode;
4620 struct inode_el *next;
4623 struct dup_block {
4624 int num_bad;
4625 struct inode_el *inode_list;
4629 * This structure stores information about a particular inode which
4630 * is sharing blocks with other inodes. This information is collected
4631 * to display to the user, so that the user knows what files he or she
4632 * is dealing with, when trying to decide how to resolve the conflict
4633 * of multiply-claimed blocks.
4635 struct dup_inode {
4636 ext2_ino_t dir;
4637 int num_dupblocks;
4638 struct ext2_inode inode;
4639 struct block_el *block_list;
4642 static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
4643 e2_blkcnt_t blockcnt, blk_t ref_blk,
4644 int ref_offset, void *priv_data);
4645 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
4646 struct dup_inode *dp, char *block_buf);
4647 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
4648 struct dup_inode *dp, char* block_buf);
4649 static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
4651 static void pass1b(e2fsck_t ctx, char *block_buf);
4652 static void pass1c(e2fsck_t ctx, char *block_buf);
4653 static void pass1d(e2fsck_t ctx, char *block_buf);
4655 static int dup_inode_count = 0;
4657 static dict_t blk_dict, ino_dict;
4659 static ext2fs_inode_bitmap inode_dup_map;
4661 static int dict_int_cmp(const void *a, const void *b)
4663 intptr_t ia, ib;
4665 ia = (intptr_t)a;
4666 ib = (intptr_t)b;
4668 return (ia-ib);
4672 * Add a duplicate block record
4674 static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
4675 struct ext2_inode *inode)
4677 dnode_t *n;
4678 struct dup_block *db;
4679 struct dup_inode *di;
4680 struct block_el *blk_el;
4681 struct inode_el *ino_el;
4683 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
4684 if (n)
4685 db = (struct dup_block *) dnode_get(n);
4686 else {
4687 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
4688 sizeof(struct dup_block), "duplicate block header");
4689 db->num_bad = 0;
4690 db->inode_list = 0;
4691 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
4693 ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
4694 sizeof(struct inode_el), "inode element");
4695 ino_el->inode = ino;
4696 ino_el->next = db->inode_list;
4697 db->inode_list = ino_el;
4698 db->num_bad++;
4700 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
4701 if (n)
4702 di = (struct dup_inode *) dnode_get(n);
4703 else {
4704 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
4705 sizeof(struct dup_inode), "duplicate inode header");
4706 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0;
4707 di->num_dupblocks = 0;
4708 di->block_list = 0;
4709 di->inode = *inode;
4710 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
4712 blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
4713 sizeof(struct block_el), "block element");
4714 blk_el->block = blk;
4715 blk_el->next = di->block_list;
4716 di->block_list = blk_el;
4717 di->num_dupblocks++;
4721 * Free a duplicate inode record
4723 static void inode_dnode_free(dnode_t *node)
4725 struct dup_inode *di;
4726 struct block_el *p, *next;
4728 di = (struct dup_inode *) dnode_get(node);
4729 for (p = di->block_list; p; p = next) {
4730 next = p->next;
4731 free(p);
4733 free(node);
4737 * Free a duplicate block record
4739 static void block_dnode_free(dnode_t *node)
4741 struct dup_block *db;
4742 struct inode_el *p, *next;
4744 db = (struct dup_block *) dnode_get(node);
4745 for (p = db->inode_list; p; p = next) {
4746 next = p->next;
4747 free(p);
4749 free(node);
4754 * Main procedure for handling duplicate blocks
4756 void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
4758 ext2_filsys fs = ctx->fs;
4759 struct problem_context pctx;
4761 clear_problem_context(&pctx);
4763 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4764 _("multiply claimed inode map"), &inode_dup_map);
4765 if (pctx.errcode) {
4766 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
4767 ctx->flags |= E2F_FLAG_ABORT;
4768 return;
4771 dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4772 dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4773 dict_set_allocator(&ino_dict, inode_dnode_free);
4774 dict_set_allocator(&blk_dict, block_dnode_free);
4776 pass1b(ctx, block_buf);
4777 pass1c(ctx, block_buf);
4778 pass1d(ctx, block_buf);
4781 * Time to free all of the accumulated data structures that we
4782 * don't need anymore.
4784 dict_free_nodes(&ino_dict);
4785 dict_free_nodes(&blk_dict);
4789 * Scan the inodes looking for inodes that contain duplicate blocks.
4791 struct process_block_struct_1b {
4792 e2fsck_t ctx;
4793 ext2_ino_t ino;
4794 int dup_blocks;
4795 struct ext2_inode *inode;
4796 struct problem_context *pctx;
4799 static void pass1b(e2fsck_t ctx, char *block_buf)
4801 ext2_filsys fs = ctx->fs;
4802 ext2_ino_t ino;
4803 struct ext2_inode inode;
4804 ext2_inode_scan scan;
4805 struct process_block_struct_1b pb;
4806 struct problem_context pctx;
4808 clear_problem_context(&pctx);
4810 if (!(ctx->options & E2F_OPT_PREEN))
4811 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
4812 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4813 &scan);
4814 if (pctx.errcode) {
4815 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4816 ctx->flags |= E2F_FLAG_ABORT;
4817 return;
4819 ctx->stashed_inode = &inode;
4820 pb.ctx = ctx;
4821 pb.pctx = &pctx;
4822 pctx.str = "pass1b";
4823 while (1) {
4824 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
4825 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
4826 continue;
4827 if (pctx.errcode) {
4828 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4829 ctx->flags |= E2F_FLAG_ABORT;
4830 return;
4832 if (!ino)
4833 break;
4834 pctx.ino = ctx->stashed_ino = ino;
4835 if ((ino != EXT2_BAD_INO) &&
4836 !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
4837 continue;
4839 pb.ino = ino;
4840 pb.dup_blocks = 0;
4841 pb.inode = &inode;
4843 if (ext2fs_inode_has_valid_blocks(&inode) ||
4844 (ino == EXT2_BAD_INO))
4845 pctx.errcode = ext2fs_block_iterate2(fs, ino,
4846 0, block_buf, process_pass1b_block, &pb);
4847 if (inode.i_file_acl)
4848 process_pass1b_block(fs, &inode.i_file_acl,
4849 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
4850 if (pb.dup_blocks) {
4851 end_problem_latch(ctx, PR_LATCH_DBLOCK);
4852 if (ino >= EXT2_FIRST_INODE(fs->super) ||
4853 ino == EXT2_ROOT_INO)
4854 dup_inode_count++;
4856 if (pctx.errcode)
4857 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
4859 ext2fs_close_inode_scan(scan);
4860 e2fsck_use_inode_shortcuts(ctx, 0);
4863 static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
4864 blk_t *block_nr,
4865 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
4866 blk_t ref_blk FSCK_ATTR((unused)),
4867 int ref_offset FSCK_ATTR((unused)),
4868 void *priv_data)
4870 struct process_block_struct_1b *p;
4871 e2fsck_t ctx;
4873 if (HOLE_BLKADDR(*block_nr))
4874 return 0;
4875 p = (struct process_block_struct_1b *) priv_data;
4876 ctx = p->ctx;
4878 if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
4879 return 0;
4881 /* OK, this is a duplicate block */
4882 if (p->ino != EXT2_BAD_INO) {
4883 p->pctx->blk = *block_nr;
4884 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
4886 p->dup_blocks++;
4887 ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
4889 add_dupe(ctx, p->ino, *block_nr, p->inode);
4891 return 0;
4895 * Pass 1c: Scan directories for inodes with duplicate blocks. This
4896 * is used so that we can print pathnames when prompting the user for
4897 * what to do.
4899 struct search_dir_struct {
4900 int count;
4901 ext2_ino_t first_inode;
4902 ext2_ino_t max_inode;
4905 static int search_dirent_proc(ext2_ino_t dir, int entry,
4906 struct ext2_dir_entry *dirent,
4907 int offset FSCK_ATTR((unused)),
4908 int blocksize FSCK_ATTR((unused)),
4909 char *buf FSCK_ATTR((unused)),
4910 void *priv_data)
4912 struct search_dir_struct *sd;
4913 struct dup_inode *p;
4914 dnode_t *n;
4916 sd = (struct search_dir_struct *) priv_data;
4918 if (dirent->inode > sd->max_inode)
4919 /* Should abort this inode, but not everything */
4920 return 0;
4922 if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
4923 !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
4924 return 0;
4926 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
4927 if (!n)
4928 return 0;
4929 p = (struct dup_inode *) dnode_get(n);
4930 p->dir = dir;
4931 sd->count--;
4933 return sd->count ? 0 : DIRENT_ABORT;
4937 static void pass1c(e2fsck_t ctx, char *block_buf)
4939 ext2_filsys fs = ctx->fs;
4940 struct search_dir_struct sd;
4941 struct problem_context pctx;
4943 clear_problem_context(&pctx);
4945 if (!(ctx->options & E2F_OPT_PREEN))
4946 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
4949 * Search through all directories to translate inodes to names
4950 * (by searching for the containing directory for that inode.)
4952 sd.count = dup_inode_count;
4953 sd.first_inode = EXT2_FIRST_INODE(fs->super);
4954 sd.max_inode = fs->super->s_inodes_count;
4955 ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
4956 search_dirent_proc, &sd);
4959 static void pass1d(e2fsck_t ctx, char *block_buf)
4961 ext2_filsys fs = ctx->fs;
4962 struct dup_inode *p, *t;
4963 struct dup_block *q;
4964 ext2_ino_t *shared, ino;
4965 int shared_len;
4966 int i;
4967 int file_ok;
4968 int meta_data = 0;
4969 struct problem_context pctx;
4970 dnode_t *n, *m;
4971 struct block_el *s;
4972 struct inode_el *r;
4974 clear_problem_context(&pctx);
4976 if (!(ctx->options & E2F_OPT_PREEN))
4977 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
4978 e2fsck_read_bitmaps(ctx);
4980 pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
4981 fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
4982 shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
4983 sizeof(ext2_ino_t) * dict_count(&ino_dict),
4984 "Shared inode list");
4985 for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
4986 p = (struct dup_inode *) dnode_get(n);
4987 shared_len = 0;
4988 file_ok = 1;
4989 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
4990 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
4991 continue;
4994 * Find all of the inodes which share blocks with this
4995 * one. First we find all of the duplicate blocks
4996 * belonging to this inode, and then search each block
4997 * get the list of inodes, and merge them together.
4999 for (s = p->block_list; s; s = s->next) {
5000 m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
5001 if (!m)
5002 continue; /* Should never happen... */
5003 q = (struct dup_block *) dnode_get(m);
5004 if (q->num_bad > 1)
5005 file_ok = 0;
5006 if (check_if_fs_block(ctx, s->block)) {
5007 file_ok = 0;
5008 meta_data = 1;
5012 * Add all inodes used by this block to the
5013 * shared[] --- which is a unique list, so
5014 * if an inode is already in shared[], don't
5015 * add it again.
5017 for (r = q->inode_list; r; r = r->next) {
5018 if (r->inode == ino)
5019 continue;
5020 for (i = 0; i < shared_len; i++)
5021 if (shared[i] == r->inode)
5022 break;
5023 if (i == shared_len) {
5024 shared[shared_len++] = r->inode;
5030 * Report the inode that we are working on
5032 pctx.inode = &p->inode;
5033 pctx.ino = ino;
5034 pctx.dir = p->dir;
5035 pctx.blkcount = p->num_dupblocks;
5036 pctx.num = meta_data ? shared_len+1 : shared_len;
5037 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
5038 pctx.blkcount = 0;
5039 pctx.num = 0;
5041 if (meta_data)
5042 fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
5044 for (i = 0; i < shared_len; i++) {
5045 m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
5046 if (!m)
5047 continue; /* should never happen */
5048 t = (struct dup_inode *) dnode_get(m);
5050 * Report the inode that we are sharing with
5052 pctx.inode = &t->inode;
5053 pctx.ino = shared[i];
5054 pctx.dir = t->dir;
5055 fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
5057 if (file_ok) {
5058 fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
5059 continue;
5061 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
5062 pctx.errcode = clone_file(ctx, ino, p, block_buf);
5063 if (pctx.errcode)
5064 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
5065 else
5066 continue;
5068 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
5069 delete_file(ctx, ino, p, block_buf);
5070 else
5071 ext2fs_unmark_valid(fs);
5073 ext2fs_free_mem(&shared);
5077 * Drop the refcount on the dup_block structure, and clear the entry
5078 * in the block_dup_map if appropriate.
5080 static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
5082 p->num_bad--;
5083 if (p->num_bad <= 0 ||
5084 (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
5085 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
5088 static int delete_file_block(ext2_filsys fs,
5089 blk_t *block_nr,
5090 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
5091 blk_t ref_block FSCK_ATTR((unused)),
5092 int ref_offset FSCK_ATTR((unused)),
5093 void *priv_data)
5095 struct process_block_struct_1b *pb;
5096 struct dup_block *p;
5097 dnode_t *n;
5098 e2fsck_t ctx;
5100 pb = (struct process_block_struct_1b *) priv_data;
5101 ctx = pb->ctx;
5103 if (HOLE_BLKADDR(*block_nr))
5104 return 0;
5106 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5107 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5108 if (n) {
5109 p = (struct dup_block *) dnode_get(n);
5110 decrement_badcount(ctx, *block_nr, p);
5111 } else
5112 bb_error_msg(_("internal error; can't find dup_blk for %d"),
5113 *block_nr);
5114 } else {
5115 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
5116 ext2fs_block_alloc_stats(fs, *block_nr, -1);
5119 return 0;
5122 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5123 struct dup_inode *dp, char* block_buf)
5125 ext2_filsys fs = ctx->fs;
5126 struct process_block_struct_1b pb;
5127 struct ext2_inode inode;
5128 struct problem_context pctx;
5129 unsigned int count;
5131 clear_problem_context(&pctx);
5132 pctx.ino = pb.ino = ino;
5133 pb.dup_blocks = dp->num_dupblocks;
5134 pb.ctx = ctx;
5135 pctx.str = "delete_file";
5137 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5138 if (ext2fs_inode_has_valid_blocks(&inode))
5139 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5140 delete_file_block, &pb);
5141 if (pctx.errcode)
5142 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5143 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5144 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5145 if (ctx->inode_bad_map)
5146 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
5147 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
5149 /* Inode may have changed by block_iterate, so reread it */
5150 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5151 inode.i_links_count = 0;
5152 inode.i_dtime = time(NULL);
5153 if (inode.i_file_acl &&
5154 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
5155 count = 1;
5156 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
5157 block_buf, -1, &count);
5158 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
5159 pctx.errcode = 0;
5160 count = 1;
5162 if (pctx.errcode) {
5163 pctx.blk = inode.i_file_acl;
5164 fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
5167 * If the count is zero, then arrange to have the
5168 * block deleted. If the block is in the block_dup_map,
5169 * also call delete_file_block since it will take care
5170 * of keeping the accounting straight.
5172 if ((count == 0) ||
5173 ext2fs_test_block_bitmap(ctx->block_dup_map,
5174 inode.i_file_acl))
5175 delete_file_block(fs, &inode.i_file_acl,
5176 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
5178 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
5181 struct clone_struct {
5182 errcode_t errcode;
5183 ext2_ino_t dir;
5184 char *buf;
5185 e2fsck_t ctx;
5188 static int clone_file_block(ext2_filsys fs,
5189 blk_t *block_nr,
5190 e2_blkcnt_t blockcnt,
5191 blk_t ref_block FSCK_ATTR((unused)),
5192 int ref_offset FSCK_ATTR((unused)),
5193 void *priv_data)
5195 struct dup_block *p;
5196 blk_t new_block;
5197 errcode_t retval;
5198 struct clone_struct *cs = (struct clone_struct *) priv_data;
5199 dnode_t *n;
5200 e2fsck_t ctx;
5202 ctx = cs->ctx;
5204 if (HOLE_BLKADDR(*block_nr))
5205 return 0;
5207 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5208 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5209 if (n) {
5210 p = (struct dup_block *) dnode_get(n);
5211 retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
5212 &new_block);
5213 if (retval) {
5214 cs->errcode = retval;
5215 return BLOCK_ABORT;
5217 if (cs->dir && (blockcnt >= 0)) {
5218 retval = ext2fs_set_dir_block(fs->dblist,
5219 cs->dir, new_block, blockcnt);
5220 if (retval) {
5221 cs->errcode = retval;
5222 return BLOCK_ABORT;
5226 retval = io_channel_read_blk(fs->io, *block_nr, 1,
5227 cs->buf);
5228 if (retval) {
5229 cs->errcode = retval;
5230 return BLOCK_ABORT;
5232 retval = io_channel_write_blk(fs->io, new_block, 1,
5233 cs->buf);
5234 if (retval) {
5235 cs->errcode = retval;
5236 return BLOCK_ABORT;
5238 decrement_badcount(ctx, *block_nr, p);
5239 *block_nr = new_block;
5240 ext2fs_mark_block_bitmap(ctx->block_found_map,
5241 new_block);
5242 ext2fs_mark_block_bitmap(fs->block_map, new_block);
5243 return BLOCK_CHANGED;
5244 } else
5245 bb_error_msg(_("internal error; can't find dup_blk for %d"),
5246 *block_nr);
5248 return 0;
5251 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5252 struct dup_inode *dp, char* block_buf)
5254 ext2_filsys fs = ctx->fs;
5255 errcode_t retval;
5256 struct clone_struct cs;
5257 struct problem_context pctx;
5258 blk_t blk;
5259 dnode_t *n;
5260 struct inode_el *ino_el;
5261 struct dup_block *db;
5262 struct dup_inode *di;
5264 clear_problem_context(&pctx);
5265 cs.errcode = 0;
5266 cs.dir = 0;
5267 cs.ctx = ctx;
5268 retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
5269 if (retval)
5270 return retval;
5272 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
5273 cs.dir = ino;
5275 pctx.ino = ino;
5276 pctx.str = "clone_file";
5277 if (ext2fs_inode_has_valid_blocks(&dp->inode))
5278 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5279 clone_file_block, &cs);
5280 ext2fs_mark_bb_dirty(fs);
5281 if (pctx.errcode) {
5282 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5283 retval = pctx.errcode;
5284 goto errout;
5286 if (cs.errcode) {
5287 bb_error_msg(_("returned from clone_file_block"));
5288 retval = cs.errcode;
5289 goto errout;
5291 /* The inode may have changed on disk, so we have to re-read it */
5292 e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
5293 blk = dp->inode.i_file_acl;
5294 if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
5295 BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
5296 BLOCK_CHANGED)) {
5297 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
5299 * If we cloned the EA block, find all other inodes
5300 * which refered to that EA block, and modify
5301 * them to point to the new EA block.
5303 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5304 db = (struct dup_block *) dnode_get(n);
5305 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
5306 if (ino_el->inode == ino)
5307 continue;
5308 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
5309 di = (struct dup_inode *) dnode_get(n);
5310 if (di->inode.i_file_acl == blk) {
5311 di->inode.i_file_acl = dp->inode.i_file_acl;
5312 e2fsck_write_inode(ctx, ino_el->inode,
5313 &di->inode, "clone file EA");
5314 decrement_badcount(ctx, blk, db);
5318 retval = 0;
5319 errout:
5320 ext2fs_free_mem(&cs.buf);
5321 return retval;
5325 * This routine returns 1 if a block overlaps with one of the superblocks,
5326 * group descriptors, inode bitmaps, or block bitmaps.
5328 static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
5330 ext2_filsys fs = ctx->fs;
5331 blk_t block;
5332 dgrp_t i;
5334 block = fs->super->s_first_data_block;
5335 for (i = 0; i < fs->group_desc_count; i++) {
5337 /* Check superblocks/block group descriptros */
5338 if (ext2fs_bg_has_super(fs, i)) {
5339 if (test_block >= block &&
5340 (test_block <= block + fs->desc_blocks))
5341 return 1;
5344 /* Check the inode table */
5345 if ((fs->group_desc[i].bg_inode_table) &&
5346 (test_block >= fs->group_desc[i].bg_inode_table) &&
5347 (test_block < (fs->group_desc[i].bg_inode_table +
5348 fs->inode_blocks_per_group)))
5349 return 1;
5351 /* Check the bitmap blocks */
5352 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
5353 (test_block == fs->group_desc[i].bg_inode_bitmap))
5354 return 1;
5356 block += fs->super->s_blocks_per_group;
5358 return 0;
5361 * pass2.c --- check directory structure
5363 * Pass 2 of e2fsck iterates through all active directory inodes, and
5364 * applies to following tests to each directory entry in the directory
5365 * blocks in the inodes:
5367 * - The length of the directory entry (rec_len) should be at
5368 * least 8 bytes, and no more than the remaining space
5369 * left in the directory block.
5370 * - The length of the name in the directory entry (name_len)
5371 * should be less than (rec_len - 8).
5372 * - The inode number in the directory entry should be within
5373 * legal bounds.
5374 * - The inode number should refer to a in-use inode.
5375 * - The first entry should be '.', and its inode should be
5376 * the inode of the directory.
5377 * - The second entry should be '..'.
5379 * To minimize disk seek time, the directory blocks are processed in
5380 * sorted order of block numbers.
5382 * Pass 2 also collects the following information:
5383 * - The inode numbers of the subdirectories for each directory.
5385 * Pass 2 relies on the following information from previous passes:
5386 * - The directory information collected in pass 1.
5387 * - The inode_used_map bitmap
5388 * - The inode_bad_map bitmap
5389 * - The inode_dir_map bitmap
5391 * Pass 2 frees the following data structures
5392 * - The inode_bad_map bitmap
5393 * - The inode_reg_map bitmap
5397 * Keeps track of how many times an inode is referenced.
5399 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
5400 static int check_dir_block(ext2_filsys fs,
5401 struct ext2_db_entry *dir_blocks_info,
5402 void *priv_data);
5403 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
5404 struct problem_context *pctx);
5405 static int update_dir_block(ext2_filsys fs,
5406 blk_t *block_nr,
5407 e2_blkcnt_t blockcnt,
5408 blk_t ref_block,
5409 int ref_offset,
5410 void *priv_data);
5411 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
5412 static int htree_depth(struct dx_dir_info *dx_dir,
5413 struct dx_dirblock_info *dx_db);
5414 static int special_dir_block_cmp(const void *a, const void *b);
5416 struct check_dir_struct {
5417 char *buf;
5418 struct problem_context pctx;
5419 int count, max;
5420 e2fsck_t ctx;
5423 static void e2fsck_pass2(e2fsck_t ctx)
5425 struct ext2_super_block *sb = ctx->fs->super;
5426 struct problem_context pctx;
5427 ext2_filsys fs = ctx->fs;
5428 char *buf;
5429 struct dir_info *dir;
5430 struct check_dir_struct cd;
5431 struct dx_dir_info *dx_dir;
5432 struct dx_dirblock_info *dx_db, *dx_parent;
5433 int b;
5434 int i, depth;
5435 problem_t code;
5436 int bad_dir;
5438 clear_problem_context(&cd.pctx);
5440 /* Pass 2 */
5442 if (!(ctx->options & E2F_OPT_PREEN))
5443 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
5445 cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
5446 0, ctx->inode_link_info,
5447 &ctx->inode_count);
5448 if (cd.pctx.errcode) {
5449 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
5450 ctx->flags |= E2F_FLAG_ABORT;
5451 return;
5453 buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
5454 "directory scan buffer");
5457 * Set up the parent pointer for the root directory, if
5458 * present. (If the root directory is not present, we will
5459 * create it in pass 3.)
5461 dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
5462 if (dir)
5463 dir->parent = EXT2_ROOT_INO;
5465 cd.buf = buf;
5466 cd.ctx = ctx;
5467 cd.count = 1;
5468 cd.max = ext2fs_dblist_count(fs->dblist);
5470 if (ctx->progress)
5471 (void) (ctx->progress)(ctx, 2, 0, cd.max);
5473 if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
5474 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
5476 cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
5477 &cd);
5478 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5479 return;
5480 if (cd.pctx.errcode) {
5481 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
5482 ctx->flags |= E2F_FLAG_ABORT;
5483 return;
5486 #ifdef ENABLE_HTREE
5487 for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
5488 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5489 return;
5490 if (dx_dir->numblocks == 0)
5491 continue;
5492 clear_problem_context(&pctx);
5493 bad_dir = 0;
5494 pctx.dir = dx_dir->ino;
5495 dx_db = dx_dir->dx_block;
5496 if (dx_db->flags & DX_FLAG_REFERENCED)
5497 dx_db->flags |= DX_FLAG_DUP_REF;
5498 else
5499 dx_db->flags |= DX_FLAG_REFERENCED;
5501 * Find all of the first and last leaf blocks, and
5502 * update their parent's min and max hash values
5504 for (b=0, dx_db = dx_dir->dx_block;
5505 b < dx_dir->numblocks;
5506 b++, dx_db++) {
5507 if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
5508 !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
5509 continue;
5510 dx_parent = &dx_dir->dx_block[dx_db->parent];
5512 * XXX Make sure dx_parent->min_hash > dx_db->min_hash
5514 if (dx_db->flags & DX_FLAG_FIRST)
5515 dx_parent->min_hash = dx_db->min_hash;
5517 * XXX Make sure dx_parent->max_hash < dx_db->max_hash
5519 if (dx_db->flags & DX_FLAG_LAST)
5520 dx_parent->max_hash = dx_db->max_hash;
5523 for (b=0, dx_db = dx_dir->dx_block;
5524 b < dx_dir->numblocks;
5525 b++, dx_db++) {
5526 pctx.blkcount = b;
5527 pctx.group = dx_db->parent;
5528 code = 0;
5529 if (!(dx_db->flags & DX_FLAG_FIRST) &&
5530 (dx_db->min_hash < dx_db->node_min_hash)) {
5531 pctx.blk = dx_db->min_hash;
5532 pctx.blk2 = dx_db->node_min_hash;
5533 code = PR_2_HTREE_MIN_HASH;
5534 fix_problem(ctx, code, &pctx);
5535 bad_dir++;
5537 if (dx_db->type == DX_DIRBLOCK_LEAF) {
5538 depth = htree_depth(dx_dir, dx_db);
5539 if (depth != dx_dir->depth) {
5540 code = PR_2_HTREE_BAD_DEPTH;
5541 fix_problem(ctx, code, &pctx);
5542 bad_dir++;
5546 * This test doesn't apply for the root block
5547 * at block #0
5549 if (b &&
5550 (dx_db->max_hash > dx_db->node_max_hash)) {
5551 pctx.blk = dx_db->max_hash;
5552 pctx.blk2 = dx_db->node_max_hash;
5553 code = PR_2_HTREE_MAX_HASH;
5554 fix_problem(ctx, code, &pctx);
5555 bad_dir++;
5557 if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
5558 code = PR_2_HTREE_NOTREF;
5559 fix_problem(ctx, code, &pctx);
5560 bad_dir++;
5561 } else if (dx_db->flags & DX_FLAG_DUP_REF) {
5562 code = PR_2_HTREE_DUPREF;
5563 fix_problem(ctx, code, &pctx);
5564 bad_dir++;
5566 if (code == 0)
5567 continue;
5569 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
5570 clear_htree(ctx, dx_dir->ino);
5571 dx_dir->numblocks = 0;
5574 #endif
5575 ext2fs_free_mem(&buf);
5576 ext2fs_free_dblist(fs->dblist);
5578 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
5579 ctx->inode_bad_map = 0;
5580 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
5581 ctx->inode_reg_map = 0;
5583 clear_problem_context(&pctx);
5584 if (ctx->large_files) {
5585 if (!(sb->s_feature_ro_compat &
5586 EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
5587 fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
5588 sb->s_feature_ro_compat |=
5589 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5590 ext2fs_mark_super_dirty(fs);
5592 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
5593 fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
5594 ext2fs_update_dynamic_rev(fs);
5595 ext2fs_mark_super_dirty(fs);
5597 } else if (!ctx->large_files &&
5598 (sb->s_feature_ro_compat &
5599 EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
5600 if (fs->flags & EXT2_FLAG_RW) {
5601 sb->s_feature_ro_compat &=
5602 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5603 ext2fs_mark_super_dirty(fs);
5608 #define MAX_DEPTH 32000
5609 static int htree_depth(struct dx_dir_info *dx_dir,
5610 struct dx_dirblock_info *dx_db)
5612 int depth = 0;
5614 while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
5615 dx_db = &dx_dir->dx_block[dx_db->parent];
5616 depth++;
5618 return depth;
5621 static int dict_de_cmp(const void *a, const void *b)
5623 const struct ext2_dir_entry *de_a, *de_b;
5624 int a_len, b_len;
5626 de_a = (const struct ext2_dir_entry *) a;
5627 a_len = de_a->name_len & 0xFF;
5628 de_b = (const struct ext2_dir_entry *) b;
5629 b_len = de_b->name_len & 0xFF;
5631 if (a_len != b_len)
5632 return (a_len - b_len);
5634 return strncmp(de_a->name, de_b->name, a_len);
5638 * This is special sort function that makes sure that directory blocks
5639 * with a dirblock of zero are sorted to the beginning of the list.
5640 * This guarantees that the root node of the htree directories are
5641 * processed first, so we know what hash version to use.
5643 static int special_dir_block_cmp(const void *a, const void *b)
5645 const struct ext2_db_entry *db_a =
5646 (const struct ext2_db_entry *) a;
5647 const struct ext2_db_entry *db_b =
5648 (const struct ext2_db_entry *) b;
5650 if (db_a->blockcnt && !db_b->blockcnt)
5651 return 1;
5653 if (!db_a->blockcnt && db_b->blockcnt)
5654 return -1;
5656 if (db_a->blk != db_b->blk)
5657 return (int) (db_a->blk - db_b->blk);
5659 if (db_a->ino != db_b->ino)
5660 return (int) (db_a->ino - db_b->ino);
5662 return (int) (db_a->blockcnt - db_b->blockcnt);
5667 * Make sure the first entry in the directory is '.', and that the
5668 * directory entry is sane.
5670 static int check_dot(e2fsck_t ctx,
5671 struct ext2_dir_entry *dirent,
5672 ext2_ino_t ino, struct problem_context *pctx)
5674 struct ext2_dir_entry *nextdir;
5675 int status = 0;
5676 int created = 0;
5677 int new_len;
5678 int problem = 0;
5680 if (!dirent->inode)
5681 problem = PR_2_MISSING_DOT;
5682 else if (((dirent->name_len & 0xFF) != 1) ||
5683 (dirent->name[0] != '.'))
5684 problem = PR_2_1ST_NOT_DOT;
5685 else if (dirent->name[1] != '\0')
5686 problem = PR_2_DOT_NULL_TERM;
5688 if (problem) {
5689 if (fix_problem(ctx, problem, pctx)) {
5690 if (dirent->rec_len < 12)
5691 dirent->rec_len = 12;
5692 dirent->inode = ino;
5693 dirent->name_len = 1;
5694 dirent->name[0] = '.';
5695 dirent->name[1] = '\0';
5696 status = 1;
5697 created = 1;
5700 if (dirent->inode != ino) {
5701 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
5702 dirent->inode = ino;
5703 status = 1;
5706 if (dirent->rec_len > 12) {
5707 new_len = dirent->rec_len - 12;
5708 if (new_len > 12) {
5709 if (created ||
5710 fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
5711 nextdir = (struct ext2_dir_entry *)
5712 ((char *) dirent + 12);
5713 dirent->rec_len = 12;
5714 nextdir->rec_len = new_len;
5715 nextdir->inode = 0;
5716 nextdir->name_len = 0;
5717 status = 1;
5721 return status;
5725 * Make sure the second entry in the directory is '..', and that the
5726 * directory entry is sane. We do not check the inode number of '..'
5727 * here; this gets done in pass 3.
5729 static int check_dotdot(e2fsck_t ctx,
5730 struct ext2_dir_entry *dirent,
5731 struct dir_info *dir, struct problem_context *pctx)
5733 int problem = 0;
5735 if (!dirent->inode)
5736 problem = PR_2_MISSING_DOT_DOT;
5737 else if (((dirent->name_len & 0xFF) != 2) ||
5738 (dirent->name[0] != '.') ||
5739 (dirent->name[1] != '.'))
5740 problem = PR_2_2ND_NOT_DOT_DOT;
5741 else if (dirent->name[2] != '\0')
5742 problem = PR_2_DOT_DOT_NULL_TERM;
5744 if (problem) {
5745 if (fix_problem(ctx, problem, pctx)) {
5746 if (dirent->rec_len < 12)
5747 dirent->rec_len = 12;
5749 * Note: we don't have the parent inode just
5750 * yet, so we will fill it in with the root
5751 * inode. This will get fixed in pass 3.
5753 dirent->inode = EXT2_ROOT_INO;
5754 dirent->name_len = 2;
5755 dirent->name[0] = '.';
5756 dirent->name[1] = '.';
5757 dirent->name[2] = '\0';
5758 return 1;
5760 return 0;
5762 dir->dotdot = dirent->inode;
5763 return 0;
5767 * Check to make sure a directory entry doesn't contain any illegal
5768 * characters.
5770 static int check_name(e2fsck_t ctx,
5771 struct ext2_dir_entry *dirent,
5772 struct problem_context *pctx)
5774 int i;
5775 int fixup = -1;
5776 int ret = 0;
5778 for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
5779 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
5780 if (fixup < 0) {
5781 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
5783 if (fixup) {
5784 dirent->name[i] = '.';
5785 ret = 1;
5789 return ret;
5793 * Check the directory filetype (if present)
5797 * Given a mode, return the ext2 file type
5799 static int ext2_file_type(unsigned int mode)
5801 if (LINUX_S_ISREG(mode))
5802 return EXT2_FT_REG_FILE;
5804 if (LINUX_S_ISDIR(mode))
5805 return EXT2_FT_DIR;
5807 if (LINUX_S_ISCHR(mode))
5808 return EXT2_FT_CHRDEV;
5810 if (LINUX_S_ISBLK(mode))
5811 return EXT2_FT_BLKDEV;
5813 if (LINUX_S_ISLNK(mode))
5814 return EXT2_FT_SYMLINK;
5816 if (LINUX_S_ISFIFO(mode))
5817 return EXT2_FT_FIFO;
5819 if (LINUX_S_ISSOCK(mode))
5820 return EXT2_FT_SOCK;
5822 return 0;
5825 static int check_filetype(e2fsck_t ctx,
5826 struct ext2_dir_entry *dirent,
5827 struct problem_context *pctx)
5829 int filetype = dirent->name_len >> 8;
5830 int should_be = EXT2_FT_UNKNOWN;
5831 struct ext2_inode inode;
5833 if (!(ctx->fs->super->s_feature_incompat &
5834 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
5835 if (filetype == 0 ||
5836 !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
5837 return 0;
5838 dirent->name_len = dirent->name_len & 0xFF;
5839 return 1;
5842 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
5843 should_be = EXT2_FT_DIR;
5844 } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
5845 dirent->inode)) {
5846 should_be = EXT2_FT_REG_FILE;
5847 } else if (ctx->inode_bad_map &&
5848 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
5849 dirent->inode))
5850 should_be = 0;
5851 else {
5852 e2fsck_read_inode(ctx, dirent->inode, &inode,
5853 "check_filetype");
5854 should_be = ext2_file_type(inode.i_mode);
5856 if (filetype == should_be)
5857 return 0;
5858 pctx->num = should_be;
5860 if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
5861 pctx) == 0)
5862 return 0;
5864 dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
5865 return 1;
5868 #ifdef ENABLE_HTREE
5869 static void parse_int_node(ext2_filsys fs,
5870 struct ext2_db_entry *db,
5871 struct check_dir_struct *cd,
5872 struct dx_dir_info *dx_dir,
5873 char *block_buf)
5875 struct ext2_dx_root_info *root;
5876 struct ext2_dx_entry *ent;
5877 struct ext2_dx_countlimit *limit;
5878 struct dx_dirblock_info *dx_db;
5879 int i, expect_limit, count;
5880 blk_t blk;
5881 ext2_dirhash_t min_hash = 0xffffffff;
5882 ext2_dirhash_t max_hash = 0;
5883 ext2_dirhash_t hash = 0, prev_hash;
5885 if (db->blockcnt == 0) {
5886 root = (struct ext2_dx_root_info *) (block_buf + 24);
5887 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5888 } else {
5889 ent = (struct ext2_dx_entry *) (block_buf+8);
5891 limit = (struct ext2_dx_countlimit *) ent;
5893 count = ext2fs_le16_to_cpu(limit->count);
5894 expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
5895 sizeof(struct ext2_dx_entry);
5896 if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5897 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
5898 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
5899 goto clear_and_exit;
5901 if (count > expect_limit) {
5902 cd->pctx.num = count;
5903 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
5904 goto clear_and_exit;
5905 count = expect_limit;
5908 for (i=0; i < count; i++) {
5909 prev_hash = hash;
5910 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5911 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5912 /* Check to make sure the block is valid */
5913 if (blk > (blk_t) dx_dir->numblocks) {
5914 cd->pctx.blk = blk;
5915 if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
5916 &cd->pctx))
5917 goto clear_and_exit;
5919 if (hash < prev_hash &&
5920 fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
5921 goto clear_and_exit;
5922 dx_db = &dx_dir->dx_block[blk];
5923 if (dx_db->flags & DX_FLAG_REFERENCED) {
5924 dx_db->flags |= DX_FLAG_DUP_REF;
5925 } else {
5926 dx_db->flags |= DX_FLAG_REFERENCED;
5927 dx_db->parent = db->blockcnt;
5929 if (hash < min_hash)
5930 min_hash = hash;
5931 if (hash > max_hash)
5932 max_hash = hash;
5933 dx_db->node_min_hash = hash;
5934 if ((i+1) < count)
5935 dx_db->node_max_hash =
5936 ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
5937 else {
5938 dx_db->node_max_hash = 0xfffffffe;
5939 dx_db->flags |= DX_FLAG_LAST;
5941 if (i == 0)
5942 dx_db->flags |= DX_FLAG_FIRST;
5944 dx_db = &dx_dir->dx_block[db->blockcnt];
5945 dx_db->min_hash = min_hash;
5946 dx_db->max_hash = max_hash;
5947 return;
5949 clear_and_exit:
5950 clear_htree(cd->ctx, cd->pctx.ino);
5951 dx_dir->numblocks = 0;
5953 #endif /* ENABLE_HTREE */
5956 * Given a busted directory, try to salvage it somehow.
5959 static void salvage_directory(ext2_filsys fs,
5960 struct ext2_dir_entry *dirent,
5961 struct ext2_dir_entry *prev,
5962 unsigned int *offset)
5964 char *cp = (char *) dirent;
5965 int left = fs->blocksize - *offset - dirent->rec_len;
5966 int name_len = dirent->name_len & 0xFF;
5969 * Special case of directory entry of size 8: copy what's left
5970 * of the directory block up to cover up the invalid hole.
5972 if ((left >= 12) && (dirent->rec_len == 8)) {
5973 memmove(cp, cp+8, left);
5974 memset(cp + left, 0, 8);
5975 return;
5978 * If the directory entry overruns the end of the directory
5979 * block, and the name is small enough to fit, then adjust the
5980 * record length.
5982 if ((left < 0) &&
5983 (name_len + 8 <= dirent->rec_len + left) &&
5984 dirent->inode <= fs->super->s_inodes_count &&
5985 strnlen(dirent->name, name_len) == name_len) {
5986 dirent->rec_len += left;
5987 return;
5990 * If the directory entry is a multiple of four, so it is
5991 * valid, let the previous directory entry absorb the invalid
5992 * one.
5994 if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
5995 prev->rec_len += dirent->rec_len;
5996 *offset += dirent->rec_len;
5997 return;
6000 * Default salvage method --- kill all of the directory
6001 * entries for the rest of the block. We will either try to
6002 * absorb it into the previous directory entry, or create a
6003 * new empty directory entry the rest of the directory block.
6005 if (prev) {
6006 prev->rec_len += fs->blocksize - *offset;
6007 *offset = fs->blocksize;
6008 } else {
6009 dirent->rec_len = fs->blocksize - *offset;
6010 dirent->name_len = 0;
6011 dirent->inode = 0;
6015 static int check_dir_block(ext2_filsys fs,
6016 struct ext2_db_entry *db,
6017 void *priv_data)
6019 struct dir_info *subdir, *dir;
6020 struct dx_dir_info *dx_dir;
6021 #ifdef ENABLE_HTREE
6022 struct dx_dirblock_info *dx_db = NULL;
6023 #endif /* ENABLE_HTREE */
6024 struct ext2_dir_entry *dirent, *prev;
6025 ext2_dirhash_t hash;
6026 unsigned int offset = 0;
6027 int dir_modified = 0;
6028 int dot_state;
6029 blk_t block_nr = db->blk;
6030 ext2_ino_t ino = db->ino;
6031 __u16 links;
6032 struct check_dir_struct *cd;
6033 char *buf;
6034 e2fsck_t ctx;
6035 int problem;
6036 struct ext2_dx_root_info *root;
6037 struct ext2_dx_countlimit *limit;
6038 static dict_t de_dict;
6039 struct problem_context pctx;
6040 int dups_found = 0;
6042 cd = (struct check_dir_struct *) priv_data;
6043 buf = cd->buf;
6044 ctx = cd->ctx;
6046 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6047 return DIRENT_ABORT;
6049 if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
6050 return DIRENT_ABORT;
6053 * Make sure the inode is still in use (could have been
6054 * deleted in the duplicate/bad blocks pass.
6056 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
6057 return 0;
6059 cd->pctx.ino = ino;
6060 cd->pctx.blk = block_nr;
6061 cd->pctx.blkcount = db->blockcnt;
6062 cd->pctx.ino2 = 0;
6063 cd->pctx.dirent = 0;
6064 cd->pctx.num = 0;
6066 if (db->blk == 0) {
6067 if (allocate_dir_block(ctx, db, &cd->pctx))
6068 return 0;
6069 block_nr = db->blk;
6072 if (db->blockcnt)
6073 dot_state = 2;
6074 else
6075 dot_state = 0;
6077 if (ctx->dirs_to_hash &&
6078 ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
6079 dups_found++;
6081 cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
6082 if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
6083 cd->pctx.errcode = 0; /* We'll handle this ourselves */
6084 if (cd->pctx.errcode) {
6085 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
6086 ctx->flags |= E2F_FLAG_ABORT;
6087 return DIRENT_ABORT;
6089 memset(buf, 0, fs->blocksize);
6091 #ifdef ENABLE_HTREE
6092 dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
6093 if (dx_dir && dx_dir->numblocks) {
6094 if (db->blockcnt >= dx_dir->numblocks) {
6095 printf("XXX should never happen!!!\n");
6096 abort();
6098 dx_db = &dx_dir->dx_block[db->blockcnt];
6099 dx_db->type = DX_DIRBLOCK_LEAF;
6100 dx_db->phys = block_nr;
6101 dx_db->min_hash = ~0;
6102 dx_db->max_hash = 0;
6104 dirent = (struct ext2_dir_entry *) buf;
6105 limit = (struct ext2_dx_countlimit *) (buf+8);
6106 if (db->blockcnt == 0) {
6107 root = (struct ext2_dx_root_info *) (buf + 24);
6108 dx_db->type = DX_DIRBLOCK_ROOT;
6109 dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
6110 if ((root->reserved_zero ||
6111 root->info_length < 8 ||
6112 root->indirect_levels > 1) &&
6113 fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
6114 clear_htree(ctx, ino);
6115 dx_dir->numblocks = 0;
6116 dx_db = 0;
6118 dx_dir->hashversion = root->hash_version;
6119 dx_dir->depth = root->indirect_levels + 1;
6120 } else if ((dirent->inode == 0) &&
6121 (dirent->rec_len == fs->blocksize) &&
6122 (dirent->name_len == 0) &&
6123 (ext2fs_le16_to_cpu(limit->limit) ==
6124 ((fs->blocksize-8) /
6125 sizeof(struct ext2_dx_entry))))
6126 dx_db->type = DX_DIRBLOCK_NODE;
6128 #endif /* ENABLE_HTREE */
6130 dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
6131 prev = 0;
6132 do {
6133 problem = 0;
6134 dirent = (struct ext2_dir_entry *) (buf + offset);
6135 cd->pctx.dirent = dirent;
6136 cd->pctx.num = offset;
6137 if (((offset + dirent->rec_len) > fs->blocksize) ||
6138 (dirent->rec_len < 12) ||
6139 ((dirent->rec_len % 4) != 0) ||
6140 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
6141 if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
6142 salvage_directory(fs, dirent, prev, &offset);
6143 dir_modified++;
6144 continue;
6145 } else
6146 goto abort_free_dict;
6148 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
6149 if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
6150 dirent->name_len = EXT2_NAME_LEN;
6151 dir_modified++;
6155 if (dot_state == 0) {
6156 if (check_dot(ctx, dirent, ino, &cd->pctx))
6157 dir_modified++;
6158 } else if (dot_state == 1) {
6159 dir = e2fsck_get_dir_info(ctx, ino);
6160 if (!dir) {
6161 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6162 goto abort_free_dict;
6164 if (check_dotdot(ctx, dirent, dir, &cd->pctx))
6165 dir_modified++;
6166 } else if (dirent->inode == ino) {
6167 problem = PR_2_LINK_DOT;
6168 if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
6169 dirent->inode = 0;
6170 dir_modified++;
6171 goto next;
6174 if (!dirent->inode)
6175 goto next;
6178 * Make sure the inode listed is a legal one.
6180 if (((dirent->inode != EXT2_ROOT_INO) &&
6181 (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
6182 (dirent->inode > fs->super->s_inodes_count)) {
6183 problem = PR_2_BAD_INO;
6184 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
6185 dirent->inode))) {
6187 * If the inode is unused, offer to clear it.
6189 problem = PR_2_UNUSED_INODE;
6190 } else if ((dot_state > 1) &&
6191 ((dirent->name_len & 0xFF) == 1) &&
6192 (dirent->name[0] == '.')) {
6194 * If there's a '.' entry in anything other
6195 * than the first directory entry, it's a
6196 * duplicate entry that should be removed.
6198 problem = PR_2_DUP_DOT;
6199 } else if ((dot_state > 1) &&
6200 ((dirent->name_len & 0xFF) == 2) &&
6201 (dirent->name[0] == '.') &&
6202 (dirent->name[1] == '.')) {
6204 * If there's a '..' entry in anything other
6205 * than the second directory entry, it's a
6206 * duplicate entry that should be removed.
6208 problem = PR_2_DUP_DOT_DOT;
6209 } else if ((dot_state > 1) &&
6210 (dirent->inode == EXT2_ROOT_INO)) {
6212 * Don't allow links to the root directory.
6213 * We check this specially to make sure we
6214 * catch this error case even if the root
6215 * directory hasn't been created yet.
6217 problem = PR_2_LINK_ROOT;
6218 } else if ((dot_state > 1) &&
6219 (dirent->name_len & 0xFF) == 0) {
6221 * Don't allow zero-length directory names.
6223 problem = PR_2_NULL_NAME;
6226 if (problem) {
6227 if (fix_problem(ctx, problem, &cd->pctx)) {
6228 dirent->inode = 0;
6229 dir_modified++;
6230 goto next;
6231 } else {
6232 ext2fs_unmark_valid(fs);
6233 if (problem == PR_2_BAD_INO)
6234 goto next;
6239 * If the inode was marked as having bad fields in
6240 * pass1, process it and offer to fix/clear it.
6241 * (We wait until now so that we can display the
6242 * pathname to the user.)
6244 if (ctx->inode_bad_map &&
6245 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
6246 dirent->inode)) {
6247 if (e2fsck_process_bad_inode(ctx, ino,
6248 dirent->inode,
6249 buf + fs->blocksize)) {
6250 dirent->inode = 0;
6251 dir_modified++;
6252 goto next;
6254 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6255 return DIRENT_ABORT;
6258 if (check_name(ctx, dirent, &cd->pctx))
6259 dir_modified++;
6261 if (check_filetype(ctx, dirent, &cd->pctx))
6262 dir_modified++;
6264 #ifdef ENABLE_HTREE
6265 if (dx_db) {
6266 ext2fs_dirhash(dx_dir->hashversion, dirent->name,
6267 (dirent->name_len & 0xFF),
6268 fs->super->s_hash_seed, &hash, 0);
6269 if (hash < dx_db->min_hash)
6270 dx_db->min_hash = hash;
6271 if (hash > dx_db->max_hash)
6272 dx_db->max_hash = hash;
6274 #endif
6277 * If this is a directory, then mark its parent in its
6278 * dir_info structure. If the parent field is already
6279 * filled in, then this directory has more than one
6280 * hard link. We assume the first link is correct,
6281 * and ask the user if he/she wants to clear this one.
6283 if ((dot_state > 1) &&
6284 (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6285 dirent->inode))) {
6286 subdir = e2fsck_get_dir_info(ctx, dirent->inode);
6287 if (!subdir) {
6288 cd->pctx.ino = dirent->inode;
6289 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6290 goto abort_free_dict;
6292 if (subdir->parent) {
6293 cd->pctx.ino2 = subdir->parent;
6294 if (fix_problem(ctx, PR_2_LINK_DIR,
6295 &cd->pctx)) {
6296 dirent->inode = 0;
6297 dir_modified++;
6298 goto next;
6300 cd->pctx.ino2 = 0;
6301 } else
6302 subdir->parent = ino;
6305 if (dups_found) {
6307 } else if (dict_lookup(&de_dict, dirent)) {
6308 clear_problem_context(&pctx);
6309 pctx.ino = ino;
6310 pctx.dirent = dirent;
6311 fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
6312 if (!ctx->dirs_to_hash)
6313 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
6314 if (ctx->dirs_to_hash)
6315 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6316 dups_found++;
6317 } else
6318 dict_alloc_insert(&de_dict, dirent, dirent);
6320 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
6321 &links);
6322 if (links > 1)
6323 ctx->fs_links_count++;
6324 ctx->fs_total_count++;
6325 next:
6326 prev = dirent;
6327 offset += dirent->rec_len;
6328 dot_state++;
6329 } while (offset < fs->blocksize);
6330 #ifdef ENABLE_HTREE
6331 if (dx_db) {
6332 cd->pctx.dir = cd->pctx.ino;
6333 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
6334 (dx_db->type == DX_DIRBLOCK_NODE))
6335 parse_int_node(fs, db, cd, dx_dir, buf);
6337 #endif /* ENABLE_HTREE */
6338 if (offset != fs->blocksize) {
6339 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
6340 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
6341 dirent->rec_len = cd->pctx.num;
6342 dir_modified++;
6345 if (dir_modified) {
6346 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
6347 if (cd->pctx.errcode) {
6348 if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
6349 &cd->pctx))
6350 goto abort_free_dict;
6352 ext2fs_mark_changed(fs);
6354 dict_free_nodes(&de_dict);
6355 return 0;
6356 abort_free_dict:
6357 dict_free_nodes(&de_dict);
6358 ctx->flags |= E2F_FLAG_ABORT;
6359 return DIRENT_ABORT;
6363 * This function is called to deallocate a block, and is an interator
6364 * functioned called by deallocate inode via ext2fs_iterate_block().
6366 static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
6367 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6368 blk_t ref_block FSCK_ATTR((unused)),
6369 int ref_offset FSCK_ATTR((unused)),
6370 void *priv_data)
6372 e2fsck_t ctx = (e2fsck_t) priv_data;
6374 if (HOLE_BLKADDR(*block_nr))
6375 return 0;
6376 if ((*block_nr < fs->super->s_first_data_block) ||
6377 (*block_nr >= fs->super->s_blocks_count))
6378 return 0;
6379 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6380 ext2fs_block_alloc_stats(fs, *block_nr, -1);
6381 return 0;
6385 * This fuction deallocates an inode
6387 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
6389 ext2_filsys fs = ctx->fs;
6390 struct ext2_inode inode;
6391 struct problem_context pctx;
6392 __u32 count;
6394 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
6395 e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
6396 inode.i_links_count = 0;
6397 inode.i_dtime = time(NULL);
6398 e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
6399 clear_problem_context(&pctx);
6400 pctx.ino = ino;
6403 * Fix up the bitmaps...
6405 e2fsck_read_bitmaps(ctx);
6406 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6407 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6408 if (ctx->inode_bad_map)
6409 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6410 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6412 if (inode.i_file_acl &&
6413 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6414 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6415 block_buf, -1, &count);
6416 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6417 pctx.errcode = 0;
6418 count = 1;
6420 if (pctx.errcode) {
6421 pctx.blk = inode.i_file_acl;
6422 fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
6423 ctx->flags |= E2F_FLAG_ABORT;
6424 return;
6426 if (count == 0) {
6427 ext2fs_unmark_block_bitmap(ctx->block_found_map,
6428 inode.i_file_acl);
6429 ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
6431 inode.i_file_acl = 0;
6434 if (!ext2fs_inode_has_valid_blocks(&inode))
6435 return;
6437 if (LINUX_S_ISREG(inode.i_mode) &&
6438 (inode.i_size_high || inode.i_size & 0x80000000UL))
6439 ctx->large_files--;
6441 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6442 deallocate_inode_block, ctx);
6443 if (pctx.errcode) {
6444 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
6445 ctx->flags |= E2F_FLAG_ABORT;
6446 return;
6451 * This fuction clears the htree flag on an inode
6453 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
6455 struct ext2_inode inode;
6457 e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
6458 inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
6459 e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
6460 if (ctx->dirs_to_hash)
6461 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6465 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
6466 ext2_ino_t ino, char *buf)
6468 ext2_filsys fs = ctx->fs;
6469 struct ext2_inode inode;
6470 int inode_modified = 0;
6471 int not_fixed = 0;
6472 unsigned char *frag, *fsize;
6473 struct problem_context pctx;
6474 int problem = 0;
6476 e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
6478 clear_problem_context(&pctx);
6479 pctx.ino = ino;
6480 pctx.dir = dir;
6481 pctx.inode = &inode;
6483 if (inode.i_file_acl &&
6484 !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
6485 fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
6486 inode.i_file_acl = 0;
6487 #if BB_BIG_ENDIAN
6489 * This is a special kludge to deal with long symlinks
6490 * on big endian systems. i_blocks had already been
6491 * decremented earlier in pass 1, but since i_file_acl
6492 * hadn't yet been cleared, ext2fs_read_inode()
6493 * assumed that the file was short symlink and would
6494 * not have byte swapped i_block[0]. Hence, we have
6495 * to byte-swap it here.
6497 if (LINUX_S_ISLNK(inode.i_mode) &&
6498 (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
6499 (inode.i_blocks == fs->blocksize >> 9))
6500 inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
6501 #endif
6502 inode_modified++;
6503 } else
6504 not_fixed++;
6506 if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
6507 !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
6508 !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
6509 !(LINUX_S_ISSOCK(inode.i_mode)))
6510 problem = PR_2_BAD_MODE;
6511 else if (LINUX_S_ISCHR(inode.i_mode)
6512 && !e2fsck_pass1_check_device_inode(fs, &inode))
6513 problem = PR_2_BAD_CHAR_DEV;
6514 else if (LINUX_S_ISBLK(inode.i_mode)
6515 && !e2fsck_pass1_check_device_inode(fs, &inode))
6516 problem = PR_2_BAD_BLOCK_DEV;
6517 else if (LINUX_S_ISFIFO(inode.i_mode)
6518 && !e2fsck_pass1_check_device_inode(fs, &inode))
6519 problem = PR_2_BAD_FIFO;
6520 else if (LINUX_S_ISSOCK(inode.i_mode)
6521 && !e2fsck_pass1_check_device_inode(fs, &inode))
6522 problem = PR_2_BAD_SOCKET;
6523 else if (LINUX_S_ISLNK(inode.i_mode)
6524 && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
6525 problem = PR_2_INVALID_SYMLINK;
6528 if (problem) {
6529 if (fix_problem(ctx, problem, &pctx)) {
6530 deallocate_inode(ctx, ino, 0);
6531 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6532 return 0;
6533 return 1;
6534 } else
6535 not_fixed++;
6536 problem = 0;
6539 if (inode.i_faddr) {
6540 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
6541 inode.i_faddr = 0;
6542 inode_modified++;
6543 } else
6544 not_fixed++;
6547 switch (fs->super->s_creator_os) {
6548 case EXT2_OS_LINUX:
6549 frag = &inode.osd2.linux2.l_i_frag;
6550 fsize = &inode.osd2.linux2.l_i_fsize;
6551 break;
6552 case EXT2_OS_HURD:
6553 frag = &inode.osd2.hurd2.h_i_frag;
6554 fsize = &inode.osd2.hurd2.h_i_fsize;
6555 break;
6556 case EXT2_OS_MASIX:
6557 frag = &inode.osd2.masix2.m_i_frag;
6558 fsize = &inode.osd2.masix2.m_i_fsize;
6559 break;
6560 default:
6561 frag = fsize = 0;
6563 if (frag && *frag) {
6564 pctx.num = *frag;
6565 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
6566 *frag = 0;
6567 inode_modified++;
6568 } else
6569 not_fixed++;
6570 pctx.num = 0;
6572 if (fsize && *fsize) {
6573 pctx.num = *fsize;
6574 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
6575 *fsize = 0;
6576 inode_modified++;
6577 } else
6578 not_fixed++;
6579 pctx.num = 0;
6582 if (inode.i_file_acl &&
6583 ((inode.i_file_acl < fs->super->s_first_data_block) ||
6584 (inode.i_file_acl >= fs->super->s_blocks_count))) {
6585 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
6586 inode.i_file_acl = 0;
6587 inode_modified++;
6588 } else
6589 not_fixed++;
6591 if (inode.i_dir_acl &&
6592 LINUX_S_ISDIR(inode.i_mode)) {
6593 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
6594 inode.i_dir_acl = 0;
6595 inode_modified++;
6596 } else
6597 not_fixed++;
6600 if (inode_modified)
6601 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
6602 if (!not_fixed)
6603 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6604 return 0;
6609 * allocate_dir_block --- this function allocates a new directory
6610 * block for a particular inode; this is done if a directory has
6611 * a "hole" in it, or if a directory has a illegal block number
6612 * that was zeroed out and now needs to be replaced.
6614 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
6615 struct problem_context *pctx)
6617 ext2_filsys fs = ctx->fs;
6618 blk_t blk;
6619 char *block;
6620 struct ext2_inode inode;
6622 if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
6623 return 1;
6626 * Read the inode and block bitmaps in; we'll be messing with
6627 * them.
6629 e2fsck_read_bitmaps(ctx);
6632 * First, find a free block
6634 pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6635 if (pctx->errcode) {
6636 pctx->str = "ext2fs_new_block";
6637 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6638 return 1;
6640 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6641 ext2fs_mark_block_bitmap(fs->block_map, blk);
6642 ext2fs_mark_bb_dirty(fs);
6645 * Now let's create the actual data block for the inode
6647 if (db->blockcnt)
6648 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
6649 else
6650 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
6651 EXT2_ROOT_INO, &block);
6653 if (pctx->errcode) {
6654 pctx->str = "ext2fs_new_dir_block";
6655 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6656 return 1;
6659 pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
6660 ext2fs_free_mem(&block);
6661 if (pctx->errcode) {
6662 pctx->str = "ext2fs_write_dir_block";
6663 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6664 return 1;
6668 * Update the inode block count
6670 e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
6671 inode.i_blocks += fs->blocksize / 512;
6672 if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
6673 inode.i_size = (db->blockcnt+1) * fs->blocksize;
6674 e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
6677 * Finally, update the block pointers for the inode
6679 db->blk = blk;
6680 pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
6681 0, update_dir_block, db);
6682 if (pctx->errcode) {
6683 pctx->str = "ext2fs_block_iterate";
6684 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6685 return 1;
6688 return 0;
6692 * This is a helper function for allocate_dir_block().
6694 static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
6695 blk_t *block_nr,
6696 e2_blkcnt_t blockcnt,
6697 blk_t ref_block FSCK_ATTR((unused)),
6698 int ref_offset FSCK_ATTR((unused)),
6699 void *priv_data)
6701 struct ext2_db_entry *db;
6703 db = (struct ext2_db_entry *) priv_data;
6704 if (db->blockcnt == (int) blockcnt) {
6705 *block_nr = db->blk;
6706 return BLOCK_CHANGED;
6708 return 0;
6712 * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
6714 * Pass #3 assures that all directories are connected to the
6715 * filesystem tree, using the following algorithm:
6717 * First, the root directory is checked to make sure it exists; if
6718 * not, e2fsck will offer to create a new one. It is then marked as
6719 * "done".
6721 * Then, pass3 interates over all directory inodes; for each directory
6722 * it attempts to trace up the filesystem tree, using dirinfo.parent
6723 * until it reaches a directory which has been marked "done". If it
6724 * cannot do so, then the directory must be disconnected, and e2fsck
6725 * will offer to reconnect it to /lost+found. While it is chasing
6726 * parent pointers up the filesystem tree, if pass3 sees a directory
6727 * twice, then it has detected a filesystem loop, and it will again
6728 * offer to reconnect the directory to /lost+found in to break the
6729 * filesystem loop.
6731 * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
6732 * reconnect inodes to /lost+found; this subroutine is also used by
6733 * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which
6734 * is responsible for creating /lost+found if it does not exist.
6736 * Pass 3 frees the following data structures:
6737 * - The dirinfo directory information cache.
6740 static void check_root(e2fsck_t ctx);
6741 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6742 struct problem_context *pctx);
6743 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
6745 static ext2fs_inode_bitmap inode_loop_detect;
6746 static ext2fs_inode_bitmap inode_done_map;
6748 static void e2fsck_pass3(e2fsck_t ctx)
6750 ext2_filsys fs = ctx->fs;
6751 int i;
6752 struct problem_context pctx;
6753 struct dir_info *dir;
6754 unsigned long maxdirs, count;
6756 clear_problem_context(&pctx);
6758 /* Pass 3 */
6760 if (!(ctx->options & E2F_OPT_PREEN))
6761 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
6764 * Allocate some bitmaps to do loop detection.
6766 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
6767 &inode_done_map);
6768 if (pctx.errcode) {
6769 pctx.num = 2;
6770 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
6771 ctx->flags |= E2F_FLAG_ABORT;
6772 goto abort_exit;
6774 check_root(ctx);
6775 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6776 goto abort_exit;
6778 ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
6780 maxdirs = e2fsck_get_num_dirinfo(ctx);
6781 count = 1;
6783 if (ctx->progress)
6784 if ((ctx->progress)(ctx, 3, 0, maxdirs))
6785 goto abort_exit;
6787 for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
6788 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6789 goto abort_exit;
6790 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
6791 goto abort_exit;
6792 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
6793 if (check_directory(ctx, dir, &pctx))
6794 goto abort_exit;
6798 * Force the creation of /lost+found if not present
6800 if ((ctx->flags & E2F_OPT_READONLY) == 0)
6801 e2fsck_get_lost_and_found(ctx, 1);
6804 * If there are any directories that need to be indexed or
6805 * optimized, do it here.
6807 e2fsck_rehash_directories(ctx);
6809 abort_exit:
6810 e2fsck_free_dir_info(ctx);
6811 ext2fs_free_inode_bitmap(inode_loop_detect);
6812 inode_loop_detect = 0;
6813 ext2fs_free_inode_bitmap(inode_done_map);
6814 inode_done_map = 0;
6818 * This makes sure the root inode is present; if not, we ask if the
6819 * user wants us to create it. Not creating it is a fatal error.
6821 static void check_root(e2fsck_t ctx)
6823 ext2_filsys fs = ctx->fs;
6824 blk_t blk;
6825 struct ext2_inode inode;
6826 char * block;
6827 struct problem_context pctx;
6829 clear_problem_context(&pctx);
6831 if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
6833 * If the root inode is not a directory, die here. The
6834 * user must have answered 'no' in pass1 when we
6835 * offered to clear it.
6837 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6838 EXT2_ROOT_INO))) {
6839 fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
6840 ctx->flags |= E2F_FLAG_ABORT;
6842 return;
6845 if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
6846 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
6847 ctx->flags |= E2F_FLAG_ABORT;
6848 return;
6851 e2fsck_read_bitmaps(ctx);
6854 * First, find a free block
6856 pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6857 if (pctx.errcode) {
6858 pctx.str = "ext2fs_new_block";
6859 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6860 ctx->flags |= E2F_FLAG_ABORT;
6861 return;
6863 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6864 ext2fs_mark_block_bitmap(fs->block_map, blk);
6865 ext2fs_mark_bb_dirty(fs);
6868 * Now let's create the actual data block for the inode
6870 pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
6871 &block);
6872 if (pctx.errcode) {
6873 pctx.str = "ext2fs_new_dir_block";
6874 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6875 ctx->flags |= E2F_FLAG_ABORT;
6876 return;
6879 pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
6880 if (pctx.errcode) {
6881 pctx.str = "ext2fs_write_dir_block";
6882 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6883 ctx->flags |= E2F_FLAG_ABORT;
6884 return;
6886 ext2fs_free_mem(&block);
6889 * Set up the inode structure
6891 memset(&inode, 0, sizeof(inode));
6892 inode.i_mode = 040755;
6893 inode.i_size = fs->blocksize;
6894 inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
6895 inode.i_links_count = 2;
6896 inode.i_blocks = fs->blocksize / 512;
6897 inode.i_block[0] = blk;
6900 * Write out the inode.
6902 pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
6903 if (pctx.errcode) {
6904 pctx.str = "ext2fs_write_inode";
6905 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6906 ctx->flags |= E2F_FLAG_ABORT;
6907 return;
6911 * Miscellaneous bookkeeping...
6913 e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
6914 ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
6915 ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
6917 ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
6918 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
6919 ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
6920 ext2fs_mark_ib_dirty(fs);
6924 * This subroutine is responsible for making sure that a particular
6925 * directory is connected to the root; if it isn't we trace it up as
6926 * far as we can go, and then offer to connect the resulting parent to
6927 * the lost+found. We have to do loop detection; if we ever discover
6928 * a loop, we treat that as a disconnected directory and offer to
6929 * reparent it to lost+found.
6931 * However, loop detection is expensive, because for very large
6932 * filesystems, the inode_loop_detect bitmap is huge, and clearing it
6933 * is non-trivial. Loops in filesystems are also a rare error case,
6934 * and we shouldn't optimize for error cases. So we try two passes of
6935 * the algorithm. The first time, we ignore loop detection and merely
6936 * increment a counter; if the counter exceeds some extreme threshold,
6937 * then we try again with the loop detection bitmap enabled.
6939 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6940 struct problem_context *pctx)
6942 ext2_filsys fs = ctx->fs;
6943 struct dir_info *p = dir;
6944 int loop_pass = 0, parent_count = 0;
6946 if (!p)
6947 return 0;
6949 while (1) {
6951 * Mark this inode as being "done"; by the time we
6952 * return from this function, the inode we either be
6953 * verified as being connected to the directory tree,
6954 * or we will have offered to reconnect this to
6955 * lost+found.
6957 * If it was marked done already, then we've reached a
6958 * parent we've already checked.
6960 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
6961 break;
6964 * If this directory doesn't have a parent, or we've
6965 * seen the parent once already, then offer to
6966 * reparent it to lost+found
6968 if (!p->parent ||
6969 (loop_pass &&
6970 (ext2fs_test_inode_bitmap(inode_loop_detect,
6971 p->parent)))) {
6972 pctx->ino = p->ino;
6973 if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
6974 if (e2fsck_reconnect_file(ctx, pctx->ino))
6975 ext2fs_unmark_valid(fs);
6976 else {
6977 p = e2fsck_get_dir_info(ctx, pctx->ino);
6978 p->parent = ctx->lost_and_found;
6979 fix_dotdot(ctx, p, ctx->lost_and_found);
6982 break;
6984 p = e2fsck_get_dir_info(ctx, p->parent);
6985 if (!p) {
6986 fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
6987 return 0;
6989 if (loop_pass) {
6990 ext2fs_mark_inode_bitmap(inode_loop_detect,
6991 p->ino);
6992 } else if (parent_count++ > 2048) {
6994 * If we've run into a path depth that's
6995 * greater than 2048, try again with the inode
6996 * loop bitmap turned on and start from the
6997 * top.
6999 loop_pass = 1;
7000 if (inode_loop_detect)
7001 ext2fs_clear_inode_bitmap(inode_loop_detect);
7002 else {
7003 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
7004 if (pctx->errcode) {
7005 pctx->num = 1;
7006 fix_problem(ctx,
7007 PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
7008 ctx->flags |= E2F_FLAG_ABORT;
7009 return -1;
7012 p = dir;
7017 * Make sure that .. and the parent directory are the same;
7018 * offer to fix it if not.
7020 if (dir->parent != dir->dotdot) {
7021 pctx->ino = dir->ino;
7022 pctx->ino2 = dir->dotdot;
7023 pctx->dir = dir->parent;
7024 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
7025 fix_dotdot(ctx, dir, dir->parent);
7027 return 0;
7031 * This routine gets the lost_and_found inode, making it a directory
7032 * if necessary
7034 ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
7036 ext2_filsys fs = ctx->fs;
7037 ext2_ino_t ino;
7038 blk_t blk;
7039 errcode_t retval;
7040 struct ext2_inode inode;
7041 char * block;
7042 static const char name[] = "lost+found";
7043 struct problem_context pctx;
7044 struct dir_info *dirinfo;
7046 if (ctx->lost_and_found)
7047 return ctx->lost_and_found;
7049 clear_problem_context(&pctx);
7051 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
7052 sizeof(name)-1, 0, &ino);
7053 if (retval && !fix)
7054 return 0;
7055 if (!retval) {
7056 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
7057 ctx->lost_and_found = ino;
7058 return ino;
7061 /* Lost+found isn't a directory! */
7062 if (!fix)
7063 return 0;
7064 pctx.ino = ino;
7065 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
7066 return 0;
7068 /* OK, unlink the old /lost+found file. */
7069 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
7070 if (pctx.errcode) {
7071 pctx.str = "ext2fs_unlink";
7072 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7073 return 0;
7075 dirinfo = e2fsck_get_dir_info(ctx, ino);
7076 if (dirinfo)
7077 dirinfo->parent = 0;
7078 e2fsck_adjust_inode_count(ctx, ino, -1);
7079 } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
7080 pctx.errcode = retval;
7081 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
7083 if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
7084 return 0;
7087 * Read the inode and block bitmaps in; we'll be messing with
7088 * them.
7090 e2fsck_read_bitmaps(ctx);
7093 * First, find a free block
7095 retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7096 if (retval) {
7097 pctx.errcode = retval;
7098 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
7099 return 0;
7101 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7102 ext2fs_block_alloc_stats(fs, blk, +1);
7105 * Next find a free inode.
7107 retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
7108 ctx->inode_used_map, &ino);
7109 if (retval) {
7110 pctx.errcode = retval;
7111 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
7112 return 0;
7114 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
7115 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
7116 ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
7119 * Now let's create the actual data block for the inode
7121 retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
7122 if (retval) {
7123 pctx.errcode = retval;
7124 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
7125 return 0;
7128 retval = ext2fs_write_dir_block(fs, blk, block);
7129 ext2fs_free_mem(&block);
7130 if (retval) {
7131 pctx.errcode = retval;
7132 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
7133 return 0;
7137 * Set up the inode structure
7139 memset(&inode, 0, sizeof(inode));
7140 inode.i_mode = 040700;
7141 inode.i_size = fs->blocksize;
7142 inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
7143 inode.i_links_count = 2;
7144 inode.i_blocks = fs->blocksize / 512;
7145 inode.i_block[0] = blk;
7148 * Next, write out the inode.
7150 pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
7151 if (pctx.errcode) {
7152 pctx.str = "ext2fs_write_inode";
7153 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7154 return 0;
7157 * Finally, create the directory link
7159 pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
7160 if (pctx.errcode) {
7161 pctx.str = "ext2fs_link";
7162 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7163 return 0;
7167 * Miscellaneous bookkeeping that needs to be kept straight.
7169 e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
7170 e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
7171 ext2fs_icount_store(ctx->inode_count, ino, 2);
7172 ext2fs_icount_store(ctx->inode_link_info, ino, 2);
7173 ctx->lost_and_found = ino;
7174 return ino;
7178 * This routine will connect a file to lost+found
7180 int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
7182 ext2_filsys fs = ctx->fs;
7183 errcode_t retval;
7184 char name[80];
7185 struct problem_context pctx;
7186 struct ext2_inode inode;
7187 int file_type = 0;
7189 clear_problem_context(&pctx);
7190 pctx.ino = ino;
7192 if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
7193 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
7194 ctx->bad_lost_and_found++;
7196 if (ctx->bad_lost_and_found) {
7197 fix_problem(ctx, PR_3_NO_LPF, &pctx);
7198 return 1;
7201 sprintf(name, "#%u", ino);
7202 if (ext2fs_read_inode(fs, ino, &inode) == 0)
7203 file_type = ext2_file_type(inode.i_mode);
7204 retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
7205 if (retval == EXT2_ET_DIR_NO_SPACE) {
7206 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
7207 return 1;
7208 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
7209 1, 0);
7210 if (retval) {
7211 pctx.errcode = retval;
7212 fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
7213 return 1;
7215 retval = ext2fs_link(fs, ctx->lost_and_found, name,
7216 ino, file_type);
7218 if (retval) {
7219 pctx.errcode = retval;
7220 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
7221 return 1;
7223 e2fsck_adjust_inode_count(ctx, ino, 1);
7225 return 0;
7229 * Utility routine to adjust the inode counts on an inode.
7231 errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
7233 ext2_filsys fs = ctx->fs;
7234 errcode_t retval;
7235 struct ext2_inode inode;
7237 if (!ino)
7238 return 0;
7240 retval = ext2fs_read_inode(fs, ino, &inode);
7241 if (retval)
7242 return retval;
7244 if (adj == 1) {
7245 ext2fs_icount_increment(ctx->inode_count, ino, 0);
7246 if (inode.i_links_count == (__u16) ~0)
7247 return 0;
7248 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
7249 inode.i_links_count++;
7250 } else if (adj == -1) {
7251 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
7252 if (inode.i_links_count == 0)
7253 return 0;
7254 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
7255 inode.i_links_count--;
7258 retval = ext2fs_write_inode(fs, ino, &inode);
7259 if (retval)
7260 return retval;
7262 return 0;
7266 * Fix parent --- this routine fixes up the parent of a directory.
7268 struct fix_dotdot_struct {
7269 ext2_filsys fs;
7270 ext2_ino_t parent;
7271 int done;
7272 e2fsck_t ctx;
7275 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
7276 int offset FSCK_ATTR((unused)),
7277 int blocksize FSCK_ATTR((unused)),
7278 char *buf FSCK_ATTR((unused)),
7279 void *priv_data)
7281 struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
7282 errcode_t retval;
7283 struct problem_context pctx;
7285 if ((dirent->name_len & 0xFF) != 2)
7286 return 0;
7287 if (strncmp(dirent->name, "..", 2))
7288 return 0;
7290 clear_problem_context(&pctx);
7292 retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
7293 if (retval) {
7294 pctx.errcode = retval;
7295 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7297 retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
7298 if (retval) {
7299 pctx.errcode = retval;
7300 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7302 dirent->inode = fp->parent;
7304 fp->done++;
7305 return DIRENT_ABORT | DIRENT_CHANGED;
7308 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
7310 ext2_filsys fs = ctx->fs;
7311 errcode_t retval;
7312 struct fix_dotdot_struct fp;
7313 struct problem_context pctx;
7315 fp.fs = fs;
7316 fp.parent = parent;
7317 fp.done = 0;
7318 fp.ctx = ctx;
7320 retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
7321 0, fix_dotdot_proc, &fp);
7322 if (retval || !fp.done) {
7323 clear_problem_context(&pctx);
7324 pctx.ino = dir->ino;
7325 pctx.errcode = retval;
7326 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
7327 PR_3_FIX_PARENT_NOFIND, &pctx);
7328 ext2fs_unmark_valid(fs);
7330 dir->dotdot = parent;
7334 * These routines are responsible for expanding a /lost+found if it is
7335 * too small.
7338 struct expand_dir_struct {
7339 int num;
7340 int guaranteed_size;
7341 int newblocks;
7342 int last_block;
7343 errcode_t err;
7344 e2fsck_t ctx;
7347 static int expand_dir_proc(ext2_filsys fs,
7348 blk_t *blocknr,
7349 e2_blkcnt_t blockcnt,
7350 blk_t ref_block FSCK_ATTR((unused)),
7351 int ref_offset FSCK_ATTR((unused)),
7352 void *priv_data)
7354 struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
7355 blk_t new_blk;
7356 static blk_t last_blk = 0;
7357 char *block;
7358 errcode_t retval;
7359 e2fsck_t ctx;
7361 ctx = es->ctx;
7363 if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
7364 return BLOCK_ABORT;
7366 if (blockcnt > 0)
7367 es->last_block = blockcnt;
7368 if (*blocknr) {
7369 last_blk = *blocknr;
7370 return 0;
7372 retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
7373 &new_blk);
7374 if (retval) {
7375 es->err = retval;
7376 return BLOCK_ABORT;
7378 if (blockcnt > 0) {
7379 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
7380 if (retval) {
7381 es->err = retval;
7382 return BLOCK_ABORT;
7384 es->num--;
7385 retval = ext2fs_write_dir_block(fs, new_blk, block);
7386 } else {
7387 retval = ext2fs_get_mem(fs->blocksize, &block);
7388 if (retval) {
7389 es->err = retval;
7390 return BLOCK_ABORT;
7392 memset(block, 0, fs->blocksize);
7393 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
7395 if (retval) {
7396 es->err = retval;
7397 return BLOCK_ABORT;
7399 ext2fs_free_mem(&block);
7400 *blocknr = new_blk;
7401 ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
7402 ext2fs_block_alloc_stats(fs, new_blk, +1);
7403 es->newblocks++;
7405 if (es->num == 0)
7406 return (BLOCK_CHANGED | BLOCK_ABORT);
7407 else
7408 return BLOCK_CHANGED;
7411 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
7412 int num, int guaranteed_size)
7414 ext2_filsys fs = ctx->fs;
7415 errcode_t retval;
7416 struct expand_dir_struct es;
7417 struct ext2_inode inode;
7419 if (!(fs->flags & EXT2_FLAG_RW))
7420 return EXT2_ET_RO_FILSYS;
7423 * Read the inode and block bitmaps in; we'll be messing with
7424 * them.
7426 e2fsck_read_bitmaps(ctx);
7428 retval = ext2fs_check_directory(fs, dir);
7429 if (retval)
7430 return retval;
7432 es.num = num;
7433 es.guaranteed_size = guaranteed_size;
7434 es.last_block = 0;
7435 es.err = 0;
7436 es.newblocks = 0;
7437 es.ctx = ctx;
7439 retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
7440 0, expand_dir_proc, &es);
7442 if (es.err)
7443 return es.err;
7446 * Update the size and block count fields in the inode.
7448 retval = ext2fs_read_inode(fs, dir, &inode);
7449 if (retval)
7450 return retval;
7452 inode.i_size = (es.last_block + 1) * fs->blocksize;
7453 inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
7455 e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
7457 return 0;
7461 * pass4.c -- pass #4 of e2fsck: Check reference counts
7463 * Pass 4 frees the following data structures:
7464 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
7468 * This routine is called when an inode is not connected to the
7469 * directory tree.
7471 * This subroutine returns 1 then the caller shouldn't bother with the
7472 * rest of the pass 4 tests.
7474 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
7476 ext2_filsys fs = ctx->fs;
7477 struct ext2_inode inode;
7478 struct problem_context pctx;
7480 e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
7481 clear_problem_context(&pctx);
7482 pctx.ino = i;
7483 pctx.inode = &inode;
7486 * Offer to delete any zero-length files that does not have
7487 * blocks. If there is an EA block, it might have useful
7488 * information, so we won't prompt to delete it, but let it be
7489 * reconnected to lost+found.
7491 if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
7492 LINUX_S_ISDIR(inode.i_mode))) {
7493 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
7494 ext2fs_icount_store(ctx->inode_link_info, i, 0);
7495 inode.i_links_count = 0;
7496 inode.i_dtime = time(NULL);
7497 e2fsck_write_inode(ctx, i, &inode,
7498 "disconnect_inode");
7500 * Fix up the bitmaps...
7502 e2fsck_read_bitmaps(ctx);
7503 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
7504 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
7505 ext2fs_inode_alloc_stats2(fs, i, -1,
7506 LINUX_S_ISDIR(inode.i_mode));
7507 return 0;
7512 * Prompt to reconnect.
7514 if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7515 if (e2fsck_reconnect_file(ctx, i))
7516 ext2fs_unmark_valid(fs);
7517 } else {
7519 * If we don't attach the inode, then skip the
7520 * i_links_test since there's no point in trying to
7521 * force i_links_count to zero.
7523 ext2fs_unmark_valid(fs);
7524 return 1;
7526 return 0;
7530 static void e2fsck_pass4(e2fsck_t ctx)
7532 ext2_filsys fs = ctx->fs;
7533 ext2_ino_t i;
7534 struct ext2_inode inode;
7535 struct problem_context pctx;
7536 __u16 link_count, link_counted;
7537 char *buf = NULL;
7538 int group, maxgroup;
7540 /* Pass 4 */
7542 clear_problem_context(&pctx);
7544 if (!(ctx->options & E2F_OPT_PREEN))
7545 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
7547 group = 0;
7548 maxgroup = fs->group_desc_count;
7549 if (ctx->progress)
7550 if ((ctx->progress)(ctx, 4, 0, maxgroup))
7551 return;
7553 for (i=1; i <= fs->super->s_inodes_count; i++) {
7554 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7555 return;
7556 if ((i % fs->super->s_inodes_per_group) == 0) {
7557 group++;
7558 if (ctx->progress)
7559 if ((ctx->progress)(ctx, 4, group, maxgroup))
7560 return;
7562 if (i == EXT2_BAD_INO ||
7563 (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
7564 continue;
7565 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
7566 (ctx->inode_imagic_map &&
7567 ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
7568 continue;
7569 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
7570 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
7571 if (link_counted == 0) {
7572 if (!buf)
7573 buf = e2fsck_allocate_memory(ctx,
7574 fs->blocksize, "bad_inode buffer");
7575 if (e2fsck_process_bad_inode(ctx, 0, i, buf))
7576 continue;
7577 if (disconnect_inode(ctx, i))
7578 continue;
7579 ext2fs_icount_fetch(ctx->inode_link_info, i,
7580 &link_count);
7581 ext2fs_icount_fetch(ctx->inode_count, i,
7582 &link_counted);
7584 if (link_counted != link_count) {
7585 e2fsck_read_inode(ctx, i, &inode, "pass4");
7586 pctx.ino = i;
7587 pctx.inode = &inode;
7588 if (link_count != inode.i_links_count) {
7589 pctx.num = link_count;
7590 fix_problem(ctx,
7591 PR_4_INCONSISTENT_COUNT, &pctx);
7593 pctx.num = link_counted;
7594 if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
7595 inode.i_links_count = link_counted;
7596 e2fsck_write_inode(ctx, i, &inode, "pass4");
7600 ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
7601 ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
7602 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
7603 ctx->inode_imagic_map = 0;
7604 ext2fs_free_mem(&buf);
7608 * pass5.c --- check block and inode bitmaps against on-disk bitmaps
7611 #define NO_BLK ((blk_t) -1)
7613 static void print_bitmap_problem(e2fsck_t ctx, int problem,
7614 struct problem_context *pctx)
7616 switch (problem) {
7617 case PR_5_BLOCK_UNUSED:
7618 if (pctx->blk == pctx->blk2)
7619 pctx->blk2 = 0;
7620 else
7621 problem = PR_5_BLOCK_RANGE_UNUSED;
7622 break;
7623 case PR_5_BLOCK_USED:
7624 if (pctx->blk == pctx->blk2)
7625 pctx->blk2 = 0;
7626 else
7627 problem = PR_5_BLOCK_RANGE_USED;
7628 break;
7629 case PR_5_INODE_UNUSED:
7630 if (pctx->ino == pctx->ino2)
7631 pctx->ino2 = 0;
7632 else
7633 problem = PR_5_INODE_RANGE_UNUSED;
7634 break;
7635 case PR_5_INODE_USED:
7636 if (pctx->ino == pctx->ino2)
7637 pctx->ino2 = 0;
7638 else
7639 problem = PR_5_INODE_RANGE_USED;
7640 break;
7642 fix_problem(ctx, problem, pctx);
7643 pctx->blk = pctx->blk2 = NO_BLK;
7644 pctx->ino = pctx->ino2 = 0;
7647 static void check_block_bitmaps(e2fsck_t ctx)
7649 ext2_filsys fs = ctx->fs;
7650 blk_t i;
7651 int *free_array;
7652 int group = 0;
7653 unsigned int blocks = 0;
7654 unsigned int free_blocks = 0;
7655 int group_free = 0;
7656 int actual, bitmap;
7657 struct problem_context pctx;
7658 int problem, save_problem, fixit, had_problem;
7659 errcode_t retval;
7661 clear_problem_context(&pctx);
7662 free_array = (int *) e2fsck_allocate_memory(ctx,
7663 fs->group_desc_count * sizeof(int), "free block count array");
7665 if ((fs->super->s_first_data_block <
7666 ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
7667 (fs->super->s_blocks_count-1 >
7668 ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
7669 pctx.num = 1;
7670 pctx.blk = fs->super->s_first_data_block;
7671 pctx.blk2 = fs->super->s_blocks_count -1;
7672 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
7673 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
7674 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7676 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7677 return;
7680 if ((fs->super->s_first_data_block <
7681 ext2fs_get_block_bitmap_start(fs->block_map)) ||
7682 (fs->super->s_blocks_count-1 >
7683 ext2fs_get_block_bitmap_end(fs->block_map))) {
7684 pctx.num = 2;
7685 pctx.blk = fs->super->s_first_data_block;
7686 pctx.blk2 = fs->super->s_blocks_count -1;
7687 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
7688 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
7689 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7691 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7692 return;
7695 redo_counts:
7696 had_problem = 0;
7697 save_problem = 0;
7698 pctx.blk = pctx.blk2 = NO_BLK;
7699 for (i = fs->super->s_first_data_block;
7700 i < fs->super->s_blocks_count;
7701 i++) {
7702 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
7703 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
7705 if (actual == bitmap)
7706 goto do_counts;
7708 if (!actual && bitmap) {
7710 * Block not used, but marked in use in the bitmap.
7712 problem = PR_5_BLOCK_UNUSED;
7713 } else {
7715 * Block used, but not marked in use in the bitmap.
7717 problem = PR_5_BLOCK_USED;
7719 if (pctx.blk == NO_BLK) {
7720 pctx.blk = pctx.blk2 = i;
7721 save_problem = problem;
7722 } else {
7723 if ((problem == save_problem) &&
7724 (pctx.blk2 == i-1))
7725 pctx.blk2++;
7726 else {
7727 print_bitmap_problem(ctx, save_problem, &pctx);
7728 pctx.blk = pctx.blk2 = i;
7729 save_problem = problem;
7732 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7733 had_problem++;
7735 do_counts:
7736 if (!bitmap) {
7737 group_free++;
7738 free_blocks++;
7740 blocks ++;
7741 if ((blocks == fs->super->s_blocks_per_group) ||
7742 (i == fs->super->s_blocks_count-1)) {
7743 free_array[group] = group_free;
7744 group ++;
7745 blocks = 0;
7746 group_free = 0;
7747 if (ctx->progress)
7748 if ((ctx->progress)(ctx, 5, group,
7749 fs->group_desc_count*2))
7750 return;
7753 if (pctx.blk != NO_BLK)
7754 print_bitmap_problem(ctx, save_problem, &pctx);
7755 if (had_problem)
7756 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
7757 else
7758 fixit = -1;
7759 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7761 if (fixit == 1) {
7762 ext2fs_free_block_bitmap(fs->block_map);
7763 retval = ext2fs_copy_bitmap(ctx->block_found_map,
7764 &fs->block_map);
7765 if (retval) {
7766 clear_problem_context(&pctx);
7767 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
7768 ctx->flags |= E2F_FLAG_ABORT;
7769 return;
7771 ext2fs_set_bitmap_padding(fs->block_map);
7772 ext2fs_mark_bb_dirty(fs);
7774 /* Redo the counts */
7775 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
7776 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7777 goto redo_counts;
7778 } else if (fixit == 0)
7779 ext2fs_unmark_valid(fs);
7781 for (i = 0; i < fs->group_desc_count; i++) {
7782 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
7783 pctx.group = i;
7784 pctx.blk = fs->group_desc[i].bg_free_blocks_count;
7785 pctx.blk2 = free_array[i];
7787 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
7788 &pctx)) {
7789 fs->group_desc[i].bg_free_blocks_count =
7790 free_array[i];
7791 ext2fs_mark_super_dirty(fs);
7792 } else
7793 ext2fs_unmark_valid(fs);
7796 if (free_blocks != fs->super->s_free_blocks_count) {
7797 pctx.group = 0;
7798 pctx.blk = fs->super->s_free_blocks_count;
7799 pctx.blk2 = free_blocks;
7801 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
7802 fs->super->s_free_blocks_count = free_blocks;
7803 ext2fs_mark_super_dirty(fs);
7804 } else
7805 ext2fs_unmark_valid(fs);
7807 ext2fs_free_mem(&free_array);
7810 static void check_inode_bitmaps(e2fsck_t ctx)
7812 ext2_filsys fs = ctx->fs;
7813 ext2_ino_t i;
7814 unsigned int free_inodes = 0;
7815 int group_free = 0;
7816 int dirs_count = 0;
7817 int group = 0;
7818 unsigned int inodes = 0;
7819 int *free_array;
7820 int *dir_array;
7821 int actual, bitmap;
7822 errcode_t retval;
7823 struct problem_context pctx;
7824 int problem, save_problem, fixit, had_problem;
7826 clear_problem_context(&pctx);
7827 free_array = (int *) e2fsck_allocate_memory(ctx,
7828 fs->group_desc_count * sizeof(int), "free inode count array");
7830 dir_array = (int *) e2fsck_allocate_memory(ctx,
7831 fs->group_desc_count * sizeof(int), "directory count array");
7833 if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
7834 (fs->super->s_inodes_count >
7835 ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
7836 pctx.num = 3;
7837 pctx.blk = 1;
7838 pctx.blk2 = fs->super->s_inodes_count;
7839 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
7840 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
7841 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7843 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7844 return;
7846 if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
7847 (fs->super->s_inodes_count >
7848 ext2fs_get_inode_bitmap_end(fs->inode_map))) {
7849 pctx.num = 4;
7850 pctx.blk = 1;
7851 pctx.blk2 = fs->super->s_inodes_count;
7852 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
7853 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
7854 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7856 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7857 return;
7860 redo_counts:
7861 had_problem = 0;
7862 save_problem = 0;
7863 pctx.ino = pctx.ino2 = 0;
7864 for (i = 1; i <= fs->super->s_inodes_count; i++) {
7865 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
7866 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
7868 if (actual == bitmap)
7869 goto do_counts;
7871 if (!actual && bitmap) {
7873 * Inode wasn't used, but marked in bitmap
7875 problem = PR_5_INODE_UNUSED;
7876 } else /* if (actual && !bitmap) */ {
7878 * Inode used, but not in bitmap
7880 problem = PR_5_INODE_USED;
7882 if (pctx.ino == 0) {
7883 pctx.ino = pctx.ino2 = i;
7884 save_problem = problem;
7885 } else {
7886 if ((problem == save_problem) &&
7887 (pctx.ino2 == i-1))
7888 pctx.ino2++;
7889 else {
7890 print_bitmap_problem(ctx, save_problem, &pctx);
7891 pctx.ino = pctx.ino2 = i;
7892 save_problem = problem;
7895 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7896 had_problem++;
7898 do_counts:
7899 if (!bitmap) {
7900 group_free++;
7901 free_inodes++;
7902 } else {
7903 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
7904 dirs_count++;
7906 inodes++;
7907 if ((inodes == fs->super->s_inodes_per_group) ||
7908 (i == fs->super->s_inodes_count)) {
7909 free_array[group] = group_free;
7910 dir_array[group] = dirs_count;
7911 group ++;
7912 inodes = 0;
7913 group_free = 0;
7914 dirs_count = 0;
7915 if (ctx->progress)
7916 if ((ctx->progress)(ctx, 5,
7917 group + fs->group_desc_count,
7918 fs->group_desc_count*2))
7919 return;
7922 if (pctx.ino)
7923 print_bitmap_problem(ctx, save_problem, &pctx);
7925 if (had_problem)
7926 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
7927 else
7928 fixit = -1;
7929 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7931 if (fixit == 1) {
7932 ext2fs_free_inode_bitmap(fs->inode_map);
7933 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
7934 &fs->inode_map);
7935 if (retval) {
7936 clear_problem_context(&pctx);
7937 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
7938 ctx->flags |= E2F_FLAG_ABORT;
7939 return;
7941 ext2fs_set_bitmap_padding(fs->inode_map);
7942 ext2fs_mark_ib_dirty(fs);
7944 /* redo counts */
7945 inodes = 0; free_inodes = 0; group_free = 0;
7946 dirs_count = 0; group = 0;
7947 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7948 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
7949 goto redo_counts;
7950 } else if (fixit == 0)
7951 ext2fs_unmark_valid(fs);
7953 for (i = 0; i < fs->group_desc_count; i++) {
7954 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
7955 pctx.group = i;
7956 pctx.ino = fs->group_desc[i].bg_free_inodes_count;
7957 pctx.ino2 = free_array[i];
7958 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
7959 &pctx)) {
7960 fs->group_desc[i].bg_free_inodes_count =
7961 free_array[i];
7962 ext2fs_mark_super_dirty(fs);
7963 } else
7964 ext2fs_unmark_valid(fs);
7966 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
7967 pctx.group = i;
7968 pctx.ino = fs->group_desc[i].bg_used_dirs_count;
7969 pctx.ino2 = dir_array[i];
7971 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
7972 &pctx)) {
7973 fs->group_desc[i].bg_used_dirs_count =
7974 dir_array[i];
7975 ext2fs_mark_super_dirty(fs);
7976 } else
7977 ext2fs_unmark_valid(fs);
7980 if (free_inodes != fs->super->s_free_inodes_count) {
7981 pctx.group = -1;
7982 pctx.ino = fs->super->s_free_inodes_count;
7983 pctx.ino2 = free_inodes;
7985 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
7986 fs->super->s_free_inodes_count = free_inodes;
7987 ext2fs_mark_super_dirty(fs);
7988 } else
7989 ext2fs_unmark_valid(fs);
7991 ext2fs_free_mem(&free_array);
7992 ext2fs_free_mem(&dir_array);
7995 static void check_inode_end(e2fsck_t ctx)
7997 ext2_filsys fs = ctx->fs;
7998 ext2_ino_t end, save_inodes_count, i;
7999 struct problem_context pctx;
8001 clear_problem_context(&pctx);
8003 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
8004 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
8005 &save_inodes_count);
8006 if (pctx.errcode) {
8007 pctx.num = 1;
8008 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8009 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8010 return;
8012 if (save_inodes_count == end)
8013 return;
8015 for (i = save_inodes_count + 1; i <= end; i++) {
8016 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
8017 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
8018 for (i = save_inodes_count + 1; i <= end; i++)
8019 ext2fs_mark_inode_bitmap(fs->inode_map,
8021 ext2fs_mark_ib_dirty(fs);
8022 } else
8023 ext2fs_unmark_valid(fs);
8024 break;
8028 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
8029 save_inodes_count, 0);
8030 if (pctx.errcode) {
8031 pctx.num = 2;
8032 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8033 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8034 return;
8038 static void check_block_end(e2fsck_t ctx)
8040 ext2_filsys fs = ctx->fs;
8041 blk_t end, save_blocks_count, i;
8042 struct problem_context pctx;
8044 clear_problem_context(&pctx);
8046 end = fs->block_map->start +
8047 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
8048 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
8049 &save_blocks_count);
8050 if (pctx.errcode) {
8051 pctx.num = 3;
8052 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8053 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8054 return;
8056 if (save_blocks_count == end)
8057 return;
8059 for (i = save_blocks_count + 1; i <= end; i++) {
8060 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
8061 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
8062 for (i = save_blocks_count + 1; i <= end; i++)
8063 ext2fs_mark_block_bitmap(fs->block_map,
8065 ext2fs_mark_bb_dirty(fs);
8066 } else
8067 ext2fs_unmark_valid(fs);
8068 break;
8072 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
8073 save_blocks_count, 0);
8074 if (pctx.errcode) {
8075 pctx.num = 4;
8076 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8077 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8078 return;
8082 static void e2fsck_pass5(e2fsck_t ctx)
8084 struct problem_context pctx;
8086 /* Pass 5 */
8088 clear_problem_context(&pctx);
8090 if (!(ctx->options & E2F_OPT_PREEN))
8091 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
8093 if (ctx->progress)
8094 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
8095 return;
8097 e2fsck_read_bitmaps(ctx);
8099 check_block_bitmaps(ctx);
8100 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8101 return;
8102 check_inode_bitmaps(ctx);
8103 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8104 return;
8105 check_inode_end(ctx);
8106 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8107 return;
8108 check_block_end(ctx);
8109 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8110 return;
8112 ext2fs_free_inode_bitmap(ctx->inode_used_map);
8113 ctx->inode_used_map = 0;
8114 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
8115 ctx->inode_dir_map = 0;
8116 ext2fs_free_block_bitmap(ctx->block_found_map);
8117 ctx->block_found_map = 0;
8121 * problem.c --- report filesystem problems to the user
8124 #define PR_PREEN_OK 0x000001 /* Don't need to do preenhalt */
8125 #define PR_NO_OK 0x000002 /* If user answers no, don't make fs invalid */
8126 #define PR_NO_DEFAULT 0x000004 /* Default to no */
8127 #define PR_MSG_ONLY 0x000008 /* Print message only */
8129 /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
8131 #define PR_FATAL 0x001000 /* Fatal error */
8132 #define PR_AFTER_CODE 0x002000 /* After asking the first question, */
8133 /* ask another */
8134 #define PR_PREEN_NOMSG 0x004000 /* Don't print a message if we're preening */
8135 #define PR_NOCOLLATE 0x008000 /* Don't collate answers for this latch */
8136 #define PR_NO_NOMSG 0x010000 /* Don't print a message if e2fsck -n */
8137 #define PR_PREEN_NO 0x020000 /* Use No as an answer if preening */
8138 #define PR_PREEN_NOHDR 0x040000 /* Don't print the preen header */
8141 #define PROMPT_NONE 0
8142 #define PROMPT_FIX 1
8143 #define PROMPT_CLEAR 2
8144 #define PROMPT_RELOCATE 3
8145 #define PROMPT_ALLOCATE 4
8146 #define PROMPT_EXPAND 5
8147 #define PROMPT_CONNECT 6
8148 #define PROMPT_CREATE 7
8149 #define PROMPT_SALVAGE 8
8150 #define PROMPT_TRUNCATE 9
8151 #define PROMPT_CLEAR_INODE 10
8152 #define PROMPT_ABORT 11
8153 #define PROMPT_SPLIT 12
8154 #define PROMPT_CONTINUE 13
8155 #define PROMPT_CLONE 14
8156 #define PROMPT_DELETE 15
8157 #define PROMPT_SUPPRESS 16
8158 #define PROMPT_UNLINK 17
8159 #define PROMPT_CLEAR_HTREE 18
8160 #define PROMPT_RECREATE 19
8161 #define PROMPT_NULL 20
8163 struct e2fsck_problem {
8164 problem_t e2p_code;
8165 const char * e2p_description;
8166 char prompt;
8167 int flags;
8168 problem_t second_code;
8171 struct latch_descr {
8172 int latch_code;
8173 problem_t question;
8174 problem_t end_message;
8175 int flags;
8179 * These are the prompts which are used to ask the user if they want
8180 * to fix a problem.
8182 static const char *const prompt[] = {
8183 N_("(no prompt)"), /* 0 */
8184 N_("Fix"), /* 1 */
8185 N_("Clear"), /* 2 */
8186 N_("Relocate"), /* 3 */
8187 N_("Allocate"), /* 4 */
8188 N_("Expand"), /* 5 */
8189 N_("Connect to /lost+found"), /* 6 */
8190 N_("Create"), /* 7 */
8191 N_("Salvage"), /* 8 */
8192 N_("Truncate"), /* 9 */
8193 N_("Clear inode"), /* 10 */
8194 N_("Abort"), /* 11 */
8195 N_("Split"), /* 12 */
8196 N_("Continue"), /* 13 */
8197 N_("Clone multiply-claimed blocks"), /* 14 */
8198 N_("Delete file"), /* 15 */
8199 N_("Suppress messages"),/* 16 */
8200 N_("Unlink"), /* 17 */
8201 N_("Clear HTree index"),/* 18 */
8202 N_("Recreate"), /* 19 */
8203 "", /* 20 */
8207 * These messages are printed when we are preen mode and we will be
8208 * automatically fixing the problem.
8210 static const char *const preen_msg[] = {
8211 N_("(NONE)"), /* 0 */
8212 N_("FIXED"), /* 1 */
8213 N_("CLEARED"), /* 2 */
8214 N_("RELOCATED"), /* 3 */
8215 N_("ALLOCATED"), /* 4 */
8216 N_("EXPANDED"), /* 5 */
8217 N_("RECONNECTED"), /* 6 */
8218 N_("CREATED"), /* 7 */
8219 N_("SALVAGED"), /* 8 */
8220 N_("TRUNCATED"), /* 9 */
8221 N_("INODE CLEARED"), /* 10 */
8222 N_("ABORTED"), /* 11 */
8223 N_("SPLIT"), /* 12 */
8224 N_("CONTINUING"), /* 13 */
8225 N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
8226 N_("FILE DELETED"), /* 15 */
8227 N_("SUPPRESSED"), /* 16 */
8228 N_("UNLINKED"), /* 17 */
8229 N_("HTREE INDEX CLEARED"),/* 18 */
8230 N_("WILL RECREATE"), /* 19 */
8231 "", /* 20 */
8234 static const struct e2fsck_problem problem_table[] = {
8236 /* Pre-Pass 1 errors */
8238 /* Block bitmap not in group */
8239 { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g. (@b %b)\n"),
8240 PROMPT_RELOCATE, PR_LATCH_RELOC },
8242 /* Inode bitmap not in group */
8243 { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g. (@b %b)\n"),
8244 PROMPT_RELOCATE, PR_LATCH_RELOC },
8246 /* Inode table not in group */
8247 { PR_0_ITABLE_NOT_GROUP,
8248 N_("@i table for @g %g is not in @g. (@b %b)\n"
8249 "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
8250 PROMPT_RELOCATE, PR_LATCH_RELOC },
8252 /* Superblock corrupt */
8253 { PR_0_SB_CORRUPT,
8254 N_("\nThe @S could not be read or does not describe a correct ext2\n"
8255 "@f. If the @v is valid and it really contains an ext2\n"
8256 "@f (and not swap or ufs or something else), then the @S\n"
8257 "is corrupt, and you might try running e2fsck with an alternate @S:\n"
8258 " e2fsck -b %S <@v>\n\n"),
8259 PROMPT_NONE, PR_FATAL },
8261 /* Filesystem size is wrong */
8262 { PR_0_FS_SIZE_WRONG,
8263 N_("The @f size (according to the @S) is %b @bs\n"
8264 "The physical size of the @v is %c @bs\n"
8265 "Either the @S or the partition table is likely to be corrupt!\n"),
8266 PROMPT_ABORT, 0 },
8268 /* Fragments not supported */
8269 { PR_0_NO_FRAGMENTS,
8270 N_("@S @b_size = %b, fragsize = %c.\n"
8271 "This version of e2fsck does not support fragment sizes different\n"
8272 "from the @b size.\n"),
8273 PROMPT_NONE, PR_FATAL },
8275 /* Bad blocks_per_group */
8276 { PR_0_BLOCKS_PER_GROUP,
8277 N_("@S @bs_per_group = %b, should have been %c\n"),
8278 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8280 /* Bad first_data_block */
8281 { PR_0_FIRST_DATA_BLOCK,
8282 N_("@S first_data_@b = %b, should have been %c\n"),
8283 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8285 /* Adding UUID to filesystem */
8286 { PR_0_ADD_UUID,
8287 N_("@f did not have a UUID; generating one.\n\n"),
8288 PROMPT_NONE, 0 },
8290 /* Relocate hint */
8291 { PR_0_RELOCATE_HINT,
8292 N_("Note: if several inode or block bitmap blocks or part\n"
8293 "of the inode table require relocation, you may wish to try\n"
8294 "running e2fsck with the '-b %S' option first. The problem\n"
8295 "may lie only with the primary block group descriptors, and\n"
8296 "the backup block group descriptors may be OK.\n\n"),
8297 PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
8299 /* Miscellaneous superblock corruption */
8300 { PR_0_MISC_CORRUPT_SUPER,
8301 N_("Corruption found in @S. (%s = %N).\n"),
8302 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8304 /* Error determing physical device size of filesystem */
8305 { PR_0_GETSIZE_ERROR,
8306 N_("Error determining size of the physical @v: %m\n"),
8307 PROMPT_NONE, PR_FATAL },
8309 /* Inode count in superblock is incorrect */
8310 { PR_0_INODE_COUNT_WRONG,
8311 N_("@i count in @S is %i, @s %j.\n"),
8312 PROMPT_FIX, 0 },
8314 { PR_0_HURD_CLEAR_FILETYPE,
8315 N_("The Hurd does not support the filetype feature.\n"),
8316 PROMPT_CLEAR, 0 },
8318 /* Journal inode is invalid */
8319 { PR_0_JOURNAL_BAD_INODE,
8320 N_("@S has an @n ext3 @j (@i %i).\n"),
8321 PROMPT_CLEAR, PR_PREEN_OK },
8323 /* The external journal has (unsupported) multiple filesystems */
8324 { PR_0_JOURNAL_UNSUPP_MULTIFS,
8325 N_("External @j has multiple @f users (unsupported).\n"),
8326 PROMPT_NONE, PR_FATAL },
8328 /* Can't find external journal */
8329 { PR_0_CANT_FIND_JOURNAL,
8330 N_("Can't find external @j\n"),
8331 PROMPT_NONE, PR_FATAL },
8333 /* External journal has bad superblock */
8334 { PR_0_EXT_JOURNAL_BAD_SUPER,
8335 N_("External @j has bad @S\n"),
8336 PROMPT_NONE, PR_FATAL },
8338 /* Superblock has a bad journal UUID */
8339 { PR_0_JOURNAL_BAD_UUID,
8340 N_("External @j does not support this @f\n"),
8341 PROMPT_NONE, PR_FATAL },
8343 /* Journal has an unknown superblock type */
8344 { PR_0_JOURNAL_UNSUPP_SUPER,
8345 N_("Ext3 @j @S is unknown type %N (unsupported).\n"
8346 "It is likely that your copy of e2fsck is old and/or doesn't "
8347 "support this @j format.\n"
8348 "It is also possible the @j @S is corrupt.\n"),
8349 PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
8351 /* Journal superblock is corrupt */
8352 { PR_0_JOURNAL_BAD_SUPER,
8353 N_("Ext3 @j @S is corrupt.\n"),
8354 PROMPT_FIX, PR_PREEN_OK },
8356 /* Superblock flag should be cleared */
8357 { PR_0_JOURNAL_HAS_JOURNAL,
8358 N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
8359 PROMPT_CLEAR, PR_PREEN_OK },
8361 /* Superblock flag is incorrect */
8362 { PR_0_JOURNAL_RECOVER_SET,
8363 N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
8364 PROMPT_CLEAR, PR_PREEN_OK },
8366 /* Journal has data, but recovery flag is clear */
8367 { PR_0_JOURNAL_RECOVERY_CLEAR,
8368 N_("ext3 recovery flag is clear, but @j has data.\n"),
8369 PROMPT_NONE, 0 },
8371 /* Ask if we should clear the journal */
8372 { PR_0_JOURNAL_RESET_JOURNAL,
8373 N_("Clear @j"),
8374 PROMPT_NULL, PR_PREEN_NOMSG },
8376 /* Ask if we should run the journal anyway */
8377 { PR_0_JOURNAL_RUN,
8378 N_("Run @j anyway"),
8379 PROMPT_NULL, 0 },
8381 /* Run the journal by default */
8382 { PR_0_JOURNAL_RUN_DEFAULT,
8383 N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
8384 PROMPT_NONE, 0 },
8386 /* Clearing orphan inode */
8387 { PR_0_ORPHAN_CLEAR_INODE,
8388 N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
8389 PROMPT_NONE, 0 },
8391 /* Illegal block found in orphaned inode */
8392 { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
8393 N_("@I @b #%B (%b) found in @o @i %i.\n"),
8394 PROMPT_NONE, 0 },
8396 /* Already cleared block found in orphaned inode */
8397 { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
8398 N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
8399 PROMPT_NONE, 0 },
8401 /* Illegal orphan inode in superblock */
8402 { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
8403 N_("@I @o @i %i in @S.\n"),
8404 PROMPT_NONE, 0 },
8406 /* Illegal inode in orphaned inode list */
8407 { PR_0_ORPHAN_ILLEGAL_INODE,
8408 N_("@I @i %i in @o @i list.\n"),
8409 PROMPT_NONE, 0 },
8411 /* Filesystem revision is 0, but feature flags are set */
8412 { PR_0_FS_REV_LEVEL,
8413 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8414 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8416 /* Journal superblock has an unknown read-only feature flag set */
8417 { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
8418 N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
8419 PROMPT_ABORT, 0 },
8421 /* Journal superblock has an unknown incompatible feature flag set */
8422 { PR_0_JOURNAL_UNSUPP_INCOMPAT,
8423 N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
8424 PROMPT_ABORT, 0 },
8426 /* Journal has unsupported version number */
8427 { PR_0_JOURNAL_UNSUPP_VERSION,
8428 N_("@j version not supported by this e2fsck.\n"),
8429 PROMPT_ABORT, 0 },
8431 /* Moving journal to hidden file */
8432 { PR_0_MOVE_JOURNAL,
8433 N_("Moving @j from /%s to hidden @i.\n\n"),
8434 PROMPT_NONE, 0 },
8436 /* Error moving journal to hidden file */
8437 { PR_0_ERR_MOVE_JOURNAL,
8438 N_("Error moving @j: %m\n\n"),
8439 PROMPT_NONE, 0 },
8441 /* Clearing V2 journal superblock */
8442 { PR_0_CLEAR_V2_JOURNAL,
8443 N_("Found @n V2 @j @S fields (from V1 @j).\n"
8444 "Clearing fields beyond the V1 @j @S...\n\n"),
8445 PROMPT_NONE, 0 },
8447 /* Backup journal inode blocks */
8448 { PR_0_BACKUP_JNL,
8449 N_("Backing up @j @i @b information.\n\n"),
8450 PROMPT_NONE, 0 },
8452 /* Reserved blocks w/o resize_inode */
8453 { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
8454 N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
8455 "is %N; @s zero. "),
8456 PROMPT_FIX, 0 },
8458 /* Resize_inode not enabled, but resize inode is non-zero */
8459 { PR_0_CLEAR_RESIZE_INODE,
8460 N_("Resize_@i not enabled, but the resize @i is non-zero. "),
8461 PROMPT_CLEAR, 0 },
8463 /* Resize inode invalid */
8464 { PR_0_RESIZE_INODE_INVALID,
8465 N_("Resize @i not valid. "),
8466 PROMPT_RECREATE, 0 },
8468 /* Pass 1 errors */
8470 /* Pass 1: Checking inodes, blocks, and sizes */
8471 { PR_1_PASS_HEADER,
8472 N_("Pass 1: Checking @is, @bs, and sizes\n"),
8473 PROMPT_NONE, 0 },
8475 /* Root directory is not an inode */
8476 { PR_1_ROOT_NO_DIR, N_("@r is not a @d. "),
8477 PROMPT_CLEAR, 0 },
8479 /* Root directory has dtime set */
8480 { PR_1_ROOT_DTIME,
8481 N_("@r has dtime set (probably due to old mke2fs). "),
8482 PROMPT_FIX, PR_PREEN_OK },
8484 /* Reserved inode has bad mode */
8485 { PR_1_RESERVED_BAD_MODE,
8486 N_("Reserved @i %i (%Q) has @n mode. "),
8487 PROMPT_CLEAR, PR_PREEN_OK },
8489 /* Deleted inode has zero dtime */
8490 { PR_1_ZERO_DTIME,
8491 N_("@D @i %i has zero dtime. "),
8492 PROMPT_FIX, PR_PREEN_OK },
8494 /* Inode in use, but dtime set */
8495 { PR_1_SET_DTIME,
8496 N_("@i %i is in use, but has dtime set. "),
8497 PROMPT_FIX, PR_PREEN_OK },
8499 /* Zero-length directory */
8500 { PR_1_ZERO_LENGTH_DIR,
8501 N_("@i %i is a @z @d. "),
8502 PROMPT_CLEAR, PR_PREEN_OK },
8504 /* Block bitmap conflicts with some other fs block */
8505 { PR_1_BB_CONFLICT,
8506 N_("@g %g's @b @B at %b @C.\n"),
8507 PROMPT_RELOCATE, 0 },
8509 /* Inode bitmap conflicts with some other fs block */
8510 { PR_1_IB_CONFLICT,
8511 N_("@g %g's @i @B at %b @C.\n"),
8512 PROMPT_RELOCATE, 0 },
8514 /* Inode table conflicts with some other fs block */
8515 { PR_1_ITABLE_CONFLICT,
8516 N_("@g %g's @i table at %b @C.\n"),
8517 PROMPT_RELOCATE, 0 },
8519 /* Block bitmap is on a bad block */
8520 { PR_1_BB_BAD_BLOCK,
8521 N_("@g %g's @b @B (%b) is bad. "),
8522 PROMPT_RELOCATE, 0 },
8524 /* Inode bitmap is on a bad block */
8525 { PR_1_IB_BAD_BLOCK,
8526 N_("@g %g's @i @B (%b) is bad. "),
8527 PROMPT_RELOCATE, 0 },
8529 /* Inode has incorrect i_size */
8530 { PR_1_BAD_I_SIZE,
8531 N_("@i %i, i_size is %Is, @s %N. "),
8532 PROMPT_FIX, PR_PREEN_OK },
8534 /* Inode has incorrect i_blocks */
8535 { PR_1_BAD_I_BLOCKS,
8536 N_("@i %i, i_@bs is %Ib, @s %N. "),
8537 PROMPT_FIX, PR_PREEN_OK },
8539 /* Illegal blocknumber in inode */
8540 { PR_1_ILLEGAL_BLOCK_NUM,
8541 N_("@I @b #%B (%b) in @i %i. "),
8542 PROMPT_CLEAR, PR_LATCH_BLOCK },
8544 /* Block number overlaps fs metadata */
8545 { PR_1_BLOCK_OVERLAPS_METADATA,
8546 N_("@b #%B (%b) overlaps @f metadata in @i %i. "),
8547 PROMPT_CLEAR, PR_LATCH_BLOCK },
8549 /* Inode has illegal blocks (latch question) */
8550 { PR_1_INODE_BLOCK_LATCH,
8551 N_("@i %i has illegal @b(s). "),
8552 PROMPT_CLEAR, 0 },
8554 /* Too many bad blocks in inode */
8555 { PR_1_TOO_MANY_BAD_BLOCKS,
8556 N_("Too many illegal @bs in @i %i.\n"),
8557 PROMPT_CLEAR_INODE, PR_NO_OK },
8559 /* Illegal block number in bad block inode */
8560 { PR_1_BB_ILLEGAL_BLOCK_NUM,
8561 N_("@I @b #%B (%b) in bad @b @i. "),
8562 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8564 /* Bad block inode has illegal blocks (latch question) */
8565 { PR_1_INODE_BBLOCK_LATCH,
8566 N_("Bad @b @i has illegal @b(s). "),
8567 PROMPT_CLEAR, 0 },
8569 /* Duplicate or bad blocks in use! */
8570 { PR_1_DUP_BLOCKS_PREENSTOP,
8571 N_("Duplicate or bad @b in use!\n"),
8572 PROMPT_NONE, 0 },
8574 /* Bad block used as bad block indirect block */
8575 { PR_1_BBINODE_BAD_METABLOCK,
8576 N_("Bad @b %b used as bad @b @i indirect @b. "),
8577 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8579 /* Inconsistency can't be fixed prompt */
8580 { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
8581 N_("\nThe bad @b @i has probably been corrupted. You probably\n"
8582 "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
8583 "in the @f.\n"),
8584 PROMPT_CONTINUE, PR_PREEN_NOMSG },
8586 /* Bad primary block */
8587 { PR_1_BAD_PRIMARY_BLOCK,
8588 N_("\nIf the @b is really bad, the @f cannot be fixed.\n"),
8589 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
8591 /* Bad primary block prompt */
8592 { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
8593 N_("You can remove this @b from the bad @b list and hope\n"
8594 "that the @b is really OK. But there are no guarantees.\n\n"),
8595 PROMPT_CLEAR, PR_PREEN_NOMSG },
8597 /* Bad primary superblock */
8598 { PR_1_BAD_PRIMARY_SUPERBLOCK,
8599 N_("The primary @S (%b) is on the bad @b list.\n"),
8600 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8602 /* Bad primary block group descriptors */
8603 { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
8604 N_("Block %b in the primary @g descriptors "
8605 "is on the bad @b list\n"),
8606 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8608 /* Bad superblock in group */
8609 { PR_1_BAD_SUPERBLOCK,
8610 N_("Warning: Group %g's @S (%b) is bad.\n"),
8611 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8613 /* Bad block group descriptors in group */
8614 { PR_1_BAD_GROUP_DESCRIPTORS,
8615 N_("Warning: Group %g's copy of the @g descriptors has a bad "
8616 "@b (%b).\n"),
8617 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8619 /* Block claimed for no reason */
8620 { PR_1_PROGERR_CLAIMED_BLOCK,
8621 N_("Programming error? @b #%b claimed for no reason in "
8622 "process_bad_@b.\n"),
8623 PROMPT_NONE, PR_PREEN_OK },
8625 /* Error allocating blocks for relocating metadata */
8626 { PR_1_RELOC_BLOCK_ALLOCATE,
8627 N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
8628 PROMPT_NONE, PR_PREEN_OK },
8630 /* Error allocating block buffer during relocation process */
8631 { PR_1_RELOC_MEMORY_ALLOCATE,
8632 N_("@A @b buffer for relocating %s\n"),
8633 PROMPT_NONE, PR_PREEN_OK },
8635 /* Relocating metadata group information from X to Y */
8636 { PR_1_RELOC_FROM_TO,
8637 N_("Relocating @g %g's %s from %b to %c...\n"),
8638 PROMPT_NONE, PR_PREEN_OK },
8640 /* Relocating metatdata group information to X */
8641 { PR_1_RELOC_TO,
8642 N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
8643 PROMPT_NONE, PR_PREEN_OK },
8645 /* Block read error during relocation process */
8646 { PR_1_RELOC_READ_ERR,
8647 N_("Warning: could not read @b %b of %s: %m\n"),
8648 PROMPT_NONE, PR_PREEN_OK },
8650 /* Block write error during relocation process */
8651 { PR_1_RELOC_WRITE_ERR,
8652 N_("Warning: could not write @b %b for %s: %m\n"),
8653 PROMPT_NONE, PR_PREEN_OK },
8655 /* Error allocating inode bitmap */
8656 { PR_1_ALLOCATE_IBITMAP_ERROR,
8657 N_("@A @i @B (%N): %m\n"),
8658 PROMPT_NONE, PR_FATAL },
8660 /* Error allocating block bitmap */
8661 { PR_1_ALLOCATE_BBITMAP_ERROR,
8662 N_("@A @b @B (%N): %m\n"),
8663 PROMPT_NONE, PR_FATAL },
8665 /* Error allocating icount structure */
8666 { PR_1_ALLOCATE_ICOUNT,
8667 N_("@A icount link information: %m\n"),
8668 PROMPT_NONE, PR_FATAL },
8670 /* Error allocating dbcount */
8671 { PR_1_ALLOCATE_DBCOUNT,
8672 N_("@A @d @b array: %m\n"),
8673 PROMPT_NONE, PR_FATAL },
8675 /* Error while scanning inodes */
8676 { PR_1_ISCAN_ERROR,
8677 N_("Error while scanning @is (%i): %m\n"),
8678 PROMPT_NONE, PR_FATAL },
8680 /* Error while iterating over blocks */
8681 { PR_1_BLOCK_ITERATE,
8682 N_("Error while iterating over @bs in @i %i: %m\n"),
8683 PROMPT_NONE, PR_FATAL },
8685 /* Error while storing inode count information */
8686 { PR_1_ICOUNT_STORE,
8687 N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
8688 PROMPT_NONE, PR_FATAL },
8690 /* Error while storing directory block information */
8691 { PR_1_ADD_DBLOCK,
8692 N_("Error storing @d @b information "
8693 "(@i=%i, @b=%b, num=%N): %m\n"),
8694 PROMPT_NONE, PR_FATAL },
8696 /* Error while reading inode (for clearing) */
8697 { PR_1_READ_INODE,
8698 N_("Error reading @i %i: %m\n"),
8699 PROMPT_NONE, PR_FATAL },
8701 /* Suppress messages prompt */
8702 { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
8704 /* Imagic flag set on an inode when filesystem doesn't support it */
8705 { PR_1_SET_IMAGIC,
8706 N_("@i %i has imagic flag set. "),
8707 PROMPT_CLEAR, 0 },
8709 /* Immutable flag set on a device or socket inode */
8710 { PR_1_SET_IMMUTABLE,
8711 N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
8712 "or append-only flag set. "),
8713 PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
8715 /* Compression flag set on an inode when filesystem doesn't support it */
8716 { PR_1_COMPR_SET,
8717 N_("@i %i has @cion flag set on @f without @cion support. "),
8718 PROMPT_CLEAR, 0 },
8720 /* Non-zero size for device, fifo or socket inode */
8721 { PR_1_SET_NONZSIZE,
8722 N_("Special (@v/socket/fifo) @i %i has non-zero size. "),
8723 PROMPT_FIX, PR_PREEN_OK },
8725 /* Filesystem revision is 0, but feature flags are set */
8726 { PR_1_FS_REV_LEVEL,
8727 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8728 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8730 /* Journal inode is not in use, but contains data */
8731 { PR_1_JOURNAL_INODE_NOT_CLEAR,
8732 N_("@j @i is not in use, but contains data. "),
8733 PROMPT_CLEAR, PR_PREEN_OK },
8735 /* Journal has bad mode */
8736 { PR_1_JOURNAL_BAD_MODE,
8737 N_("@j is not regular file. "),
8738 PROMPT_FIX, PR_PREEN_OK },
8740 /* Deal with inodes that were part of orphan linked list */
8741 { PR_1_LOW_DTIME,
8742 N_("@i %i was part of the @o @i list. "),
8743 PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
8745 /* Deal with inodes that were part of corrupted orphan linked
8746 list (latch question) */
8747 { PR_1_ORPHAN_LIST_REFUGEES,
8748 N_("@is that were part of a corrupted orphan linked list found. "),
8749 PROMPT_FIX, 0 },
8751 /* Error allocating refcount structure */
8752 { PR_1_ALLOCATE_REFCOUNT,
8753 N_("@A refcount structure (%N): %m\n"),
8754 PROMPT_NONE, PR_FATAL },
8756 /* Error reading extended attribute block */
8757 { PR_1_READ_EA_BLOCK,
8758 N_("Error reading @a @b %b for @i %i. "),
8759 PROMPT_CLEAR, 0 },
8761 /* Invalid extended attribute block */
8762 { PR_1_BAD_EA_BLOCK,
8763 N_("@i %i has a bad @a @b %b. "),
8764 PROMPT_CLEAR, 0 },
8766 /* Error reading Extended Attribute block while fixing refcount */
8767 { PR_1_EXTATTR_READ_ABORT,
8768 N_("Error reading @a @b %b (%m). "),
8769 PROMPT_ABORT, 0 },
8771 /* Extended attribute reference count incorrect */
8772 { PR_1_EXTATTR_REFCOUNT,
8773 N_("@a @b %b has reference count %B, @s %N. "),
8774 PROMPT_FIX, 0 },
8776 /* Error writing Extended Attribute block while fixing refcount */
8777 { PR_1_EXTATTR_WRITE,
8778 N_("Error writing @a @b %b (%m). "),
8779 PROMPT_ABORT, 0 },
8781 /* Multiple EA blocks not supported */
8782 { PR_1_EA_MULTI_BLOCK,
8783 N_("@a @b %b has h_@bs > 1. "),
8784 PROMPT_CLEAR, 0},
8786 /* Error allocating EA region allocation structure */
8787 { PR_1_EA_ALLOC_REGION,
8788 N_("@A @a @b %b. "),
8789 PROMPT_ABORT, 0},
8791 /* Error EA allocation collision */
8792 { PR_1_EA_ALLOC_COLLISION,
8793 N_("@a @b %b is corrupt (allocation collision). "),
8794 PROMPT_CLEAR, 0},
8796 /* Bad extended attribute name */
8797 { PR_1_EA_BAD_NAME,
8798 N_("@a @b %b is corrupt (@n name). "),
8799 PROMPT_CLEAR, 0},
8801 /* Bad extended attribute value */
8802 { PR_1_EA_BAD_VALUE,
8803 N_("@a @b %b is corrupt (@n value). "),
8804 PROMPT_CLEAR, 0},
8806 /* Inode too big (latch question) */
8807 { PR_1_INODE_TOOBIG,
8808 N_("@i %i is too big. "), PROMPT_TRUNCATE, 0 },
8810 /* Directory too big */
8811 { PR_1_TOOBIG_DIR,
8812 N_("@b #%B (%b) causes @d to be too big. "),
8813 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8815 /* Regular file too big */
8816 { PR_1_TOOBIG_REG,
8817 N_("@b #%B (%b) causes file to be too big. "),
8818 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8820 /* Symlink too big */
8821 { PR_1_TOOBIG_SYMLINK,
8822 N_("@b #%B (%b) causes symlink to be too big. "),
8823 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8825 /* INDEX_FL flag set on a non-HTREE filesystem */
8826 { PR_1_HTREE_SET,
8827 N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
8828 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8830 /* INDEX_FL flag set on a non-directory */
8831 { PR_1_HTREE_NODIR,
8832 N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
8833 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8835 /* Invalid root node in HTREE directory */
8836 { PR_1_HTREE_BADROOT,
8837 N_("@h %i has an @n root node.\n"),
8838 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8840 /* Unsupported hash version in HTREE directory */
8841 { PR_1_HTREE_HASHV,
8842 N_("@h %i has an unsupported hash version (%N)\n"),
8843 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8845 /* Incompatible flag in HTREE root node */
8846 { PR_1_HTREE_INCOMPAT,
8847 N_("@h %i uses an incompatible htree root node flag.\n"),
8848 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8850 /* HTREE too deep */
8851 { PR_1_HTREE_DEPTH,
8852 N_("@h %i has a tree depth (%N) which is too big\n"),
8853 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8855 /* Bad block has indirect block that conflicts with filesystem block */
8856 { PR_1_BB_FS_BLOCK,
8857 N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
8858 "@f metadata. "),
8859 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8861 /* Resize inode failed */
8862 { PR_1_RESIZE_INODE_CREATE,
8863 N_("Resize @i (re)creation failed: %m."),
8864 PROMPT_ABORT, 0 },
8866 /* invalid inode->i_extra_isize */
8867 { PR_1_EXTRA_ISIZE,
8868 N_("@i %i has a extra size (%IS) which is @n\n"),
8869 PROMPT_FIX, PR_PREEN_OK },
8871 /* invalid ea entry->e_name_len */
8872 { PR_1_ATTR_NAME_LEN,
8873 N_("@a in @i %i has a namelen (%N) which is @n\n"),
8874 PROMPT_CLEAR, PR_PREEN_OK },
8876 /* invalid ea entry->e_value_size */
8877 { PR_1_ATTR_VALUE_SIZE,
8878 N_("@a in @i %i has a value size (%N) which is @n\n"),
8879 PROMPT_CLEAR, PR_PREEN_OK },
8881 /* invalid ea entry->e_value_offs */
8882 { PR_1_ATTR_VALUE_OFFSET,
8883 N_("@a in @i %i has a value offset (%N) which is @n\n"),
8884 PROMPT_CLEAR, PR_PREEN_OK },
8886 /* invalid ea entry->e_value_block */
8887 { PR_1_ATTR_VALUE_BLOCK,
8888 N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
8889 PROMPT_CLEAR, PR_PREEN_OK },
8891 /* invalid ea entry->e_hash */
8892 { PR_1_ATTR_HASH,
8893 N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
8894 PROMPT_CLEAR, PR_PREEN_OK },
8896 /* Pass 1b errors */
8898 /* Pass 1B: Rescan for duplicate/bad blocks */
8899 { PR_1B_PASS_HEADER,
8900 N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
8901 "Pass 1B: Rescanning for @m @bs\n"),
8902 PROMPT_NONE, 0 },
8904 /* Duplicate/bad block(s) header */
8905 { PR_1B_DUP_BLOCK_HEADER,
8906 N_("@m @b(s) in @i %i:"),
8907 PROMPT_NONE, 0 },
8909 /* Duplicate/bad block(s) in inode */
8910 { PR_1B_DUP_BLOCK,
8911 " %b",
8912 PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
8914 /* Duplicate/bad block(s) end */
8915 { PR_1B_DUP_BLOCK_END,
8916 "\n",
8917 PROMPT_NONE, PR_PREEN_NOHDR },
8919 /* Error while scanning inodes */
8920 { PR_1B_ISCAN_ERROR,
8921 N_("Error while scanning inodes (%i): %m\n"),
8922 PROMPT_NONE, PR_FATAL },
8924 /* Error allocating inode bitmap */
8925 { PR_1B_ALLOCATE_IBITMAP_ERROR,
8926 N_("@A @i @B (@i_dup_map): %m\n"),
8927 PROMPT_NONE, PR_FATAL },
8929 /* Error while iterating over blocks */
8930 { PR_1B_BLOCK_ITERATE,
8931 N_("Error while iterating over @bs in @i %i (%s): %m\n"),
8932 PROMPT_NONE, 0 },
8934 /* Error adjusting EA refcount */
8935 { PR_1B_ADJ_EA_REFCOUNT,
8936 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
8937 PROMPT_NONE, 0 },
8940 /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
8941 { PR_1C_PASS_HEADER,
8942 N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
8943 PROMPT_NONE, 0 },
8946 /* Pass 1D: Reconciling multiply-claimed blocks */
8947 { PR_1D_PASS_HEADER,
8948 N_("Pass 1D: Reconciling @m @bs\n"),
8949 PROMPT_NONE, 0 },
8951 /* File has duplicate blocks */
8952 { PR_1D_DUP_FILE,
8953 N_("File %Q (@i #%i, mod time %IM)\n"
8954 " has %B @m @b(s), shared with %N file(s):\n"),
8955 PROMPT_NONE, 0 },
8957 /* List of files sharing duplicate blocks */
8958 { PR_1D_DUP_FILE_LIST,
8959 N_("\t%Q (@i #%i, mod time %IM)\n"),
8960 PROMPT_NONE, 0 },
8962 /* File sharing blocks with filesystem metadata */
8963 { PR_1D_SHARE_METADATA,
8964 N_("\t<@f metadata>\n"),
8965 PROMPT_NONE, 0 },
8967 /* Report of how many duplicate/bad inodes */
8968 { PR_1D_NUM_DUP_INODES,
8969 N_("(There are %N @is containing @m @bs.)\n\n"),
8970 PROMPT_NONE, 0 },
8972 /* Duplicated blocks already reassigned or cloned. */
8973 { PR_1D_DUP_BLOCKS_DEALT,
8974 N_("@m @bs already reassigned or cloned.\n\n"),
8975 PROMPT_NONE, 0 },
8977 /* Clone duplicate/bad blocks? */
8978 { PR_1D_CLONE_QUESTION,
8979 "", PROMPT_CLONE, PR_NO_OK },
8981 /* Delete file? */
8982 { PR_1D_DELETE_QUESTION,
8983 "", PROMPT_DELETE, 0 },
8985 /* Couldn't clone file (error) */
8986 { PR_1D_CLONE_ERROR,
8987 N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
8989 /* Pass 2 errors */
8991 /* Pass 2: Checking directory structure */
8992 { PR_2_PASS_HEADER,
8993 N_("Pass 2: Checking @d structure\n"),
8994 PROMPT_NONE, 0 },
8996 /* Bad inode number for '.' */
8997 { PR_2_BAD_INODE_DOT,
8998 N_("@n @i number for '.' in @d @i %i.\n"),
8999 PROMPT_FIX, 0 },
9001 /* Directory entry has bad inode number */
9002 { PR_2_BAD_INO,
9003 N_("@E has @n @i #: %Di.\n"),
9004 PROMPT_CLEAR, 0 },
9006 /* Directory entry has deleted or unused inode */
9007 { PR_2_UNUSED_INODE,
9008 N_("@E has @D/unused @i %Di. "),
9009 PROMPT_CLEAR, PR_PREEN_OK },
9011 /* Directry entry is link to '.' */
9012 { PR_2_LINK_DOT,
9013 N_("@E @L to '.' "),
9014 PROMPT_CLEAR, 0 },
9016 /* Directory entry points to inode now located in a bad block */
9017 { PR_2_BB_INODE,
9018 N_("@E points to @i (%Di) located in a bad @b.\n"),
9019 PROMPT_CLEAR, 0 },
9021 /* Directory entry contains a link to a directory */
9022 { PR_2_LINK_DIR,
9023 N_("@E @L to @d %P (%Di).\n"),
9024 PROMPT_CLEAR, 0 },
9026 /* Directory entry contains a link to the root directry */
9027 { PR_2_LINK_ROOT,
9028 N_("@E @L to the @r.\n"),
9029 PROMPT_CLEAR, 0 },
9031 /* Directory entry has illegal characters in its name */
9032 { PR_2_BAD_NAME,
9033 N_("@E has illegal characters in its name.\n"),
9034 PROMPT_FIX, 0 },
9036 /* Missing '.' in directory inode */
9037 { PR_2_MISSING_DOT,
9038 N_("Missing '.' in @d @i %i.\n"),
9039 PROMPT_FIX, 0 },
9041 /* Missing '..' in directory inode */
9042 { PR_2_MISSING_DOT_DOT,
9043 N_("Missing '..' in @d @i %i.\n"),
9044 PROMPT_FIX, 0 },
9046 /* First entry in directory inode doesn't contain '.' */
9047 { PR_2_1ST_NOT_DOT,
9048 N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
9049 PROMPT_FIX, 0 },
9051 /* Second entry in directory inode doesn't contain '..' */
9052 { PR_2_2ND_NOT_DOT_DOT,
9053 N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
9054 PROMPT_FIX, 0 },
9056 /* i_faddr should be zero */
9057 { PR_2_FADDR_ZERO,
9058 N_("i_faddr @F %IF, @s zero.\n"),
9059 PROMPT_CLEAR, 0 },
9061 /* i_file_acl should be zero */
9062 { PR_2_FILE_ACL_ZERO,
9063 N_("i_file_acl @F %If, @s zero.\n"),
9064 PROMPT_CLEAR, 0 },
9066 /* i_dir_acl should be zero */
9067 { PR_2_DIR_ACL_ZERO,
9068 N_("i_dir_acl @F %Id, @s zero.\n"),
9069 PROMPT_CLEAR, 0 },
9071 /* i_frag should be zero */
9072 { PR_2_FRAG_ZERO,
9073 N_("i_frag @F %N, @s zero.\n"),
9074 PROMPT_CLEAR, 0 },
9076 /* i_fsize should be zero */
9077 { PR_2_FSIZE_ZERO,
9078 N_("i_fsize @F %N, @s zero.\n"),
9079 PROMPT_CLEAR, 0 },
9081 /* inode has bad mode */
9082 { PR_2_BAD_MODE,
9083 N_("@i %i (%Q) has @n mode (%Im).\n"),
9084 PROMPT_CLEAR, 0 },
9086 /* directory corrupted */
9087 { PR_2_DIR_CORRUPTED,
9088 N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
9089 PROMPT_SALVAGE, 0 },
9091 /* filename too long */
9092 { PR_2_FILENAME_LONG,
9093 N_("@d @i %i, @b %B, offset %N: filename too long\n"),
9094 PROMPT_TRUNCATE, 0 },
9096 /* Directory inode has a missing block (hole) */
9097 { PR_2_DIRECTORY_HOLE,
9098 N_("@d @i %i has an unallocated @b #%B. "),
9099 PROMPT_ALLOCATE, 0 },
9101 /* '.' is not NULL terminated */
9102 { PR_2_DOT_NULL_TERM,
9103 N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
9104 PROMPT_FIX, 0 },
9106 /* '..' is not NULL terminated */
9107 { PR_2_DOT_DOT_NULL_TERM,
9108 N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
9109 PROMPT_FIX, 0 },
9111 /* Illegal character device inode */
9112 { PR_2_BAD_CHAR_DEV,
9113 N_("@i %i (%Q) is an @I character @v.\n"),
9114 PROMPT_CLEAR, 0 },
9116 /* Illegal block device inode */
9117 { PR_2_BAD_BLOCK_DEV,
9118 N_("@i %i (%Q) is an @I @b @v.\n"),
9119 PROMPT_CLEAR, 0 },
9121 /* Duplicate '.' entry */
9122 { PR_2_DUP_DOT,
9123 N_("@E is duplicate '.' @e.\n"),
9124 PROMPT_FIX, 0 },
9126 /* Duplicate '..' entry */
9127 { PR_2_DUP_DOT_DOT,
9128 N_("@E is duplicate '..' @e.\n"),
9129 PROMPT_FIX, 0 },
9131 /* Internal error: couldn't find dir_info */
9132 { PR_2_NO_DIRINFO,
9133 N_("Internal error: cannot find dir_info for %i.\n"),
9134 PROMPT_NONE, PR_FATAL },
9136 /* Final rec_len is wrong */
9137 { PR_2_FINAL_RECLEN,
9138 N_("@E has rec_len of %Dr, @s %N.\n"),
9139 PROMPT_FIX, 0 },
9141 /* Error allocating icount structure */
9142 { PR_2_ALLOCATE_ICOUNT,
9143 N_("@A icount structure: %m\n"),
9144 PROMPT_NONE, PR_FATAL },
9146 /* Error iterating over directory blocks */
9147 { PR_2_DBLIST_ITERATE,
9148 N_("Error iterating over @d @bs: %m\n"),
9149 PROMPT_NONE, PR_FATAL },
9151 /* Error reading directory block */
9152 { PR_2_READ_DIRBLOCK,
9153 N_("Error reading @d @b %b (@i %i): %m\n"),
9154 PROMPT_CONTINUE, 0 },
9156 /* Error writing directory block */
9157 { PR_2_WRITE_DIRBLOCK,
9158 N_("Error writing @d @b %b (@i %i): %m\n"),
9159 PROMPT_CONTINUE, 0 },
9161 /* Error allocating new directory block */
9162 { PR_2_ALLOC_DIRBOCK,
9163 N_("@A new @d @b for @i %i (%s): %m\n"),
9164 PROMPT_NONE, 0 },
9166 /* Error deallocating inode */
9167 { PR_2_DEALLOC_INODE,
9168 N_("Error deallocating @i %i: %m\n"),
9169 PROMPT_NONE, PR_FATAL },
9171 /* Directory entry for '.' is big. Split? */
9172 { PR_2_SPLIT_DOT,
9173 N_("@d @e for '.' is big. "),
9174 PROMPT_SPLIT, PR_NO_OK },
9176 /* Illegal FIFO inode */
9177 { PR_2_BAD_FIFO,
9178 N_("@i %i (%Q) is an @I FIFO.\n"),
9179 PROMPT_CLEAR, 0 },
9181 /* Illegal socket inode */
9182 { PR_2_BAD_SOCKET,
9183 N_("@i %i (%Q) is an @I socket.\n"),
9184 PROMPT_CLEAR, 0 },
9186 /* Directory filetype not set */
9187 { PR_2_SET_FILETYPE,
9188 N_("Setting filetype for @E to %N.\n"),
9189 PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
9191 /* Directory filetype incorrect */
9192 { PR_2_BAD_FILETYPE,
9193 N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
9194 PROMPT_FIX, 0 },
9196 /* Directory filetype set on filesystem */
9197 { PR_2_CLEAR_FILETYPE,
9198 N_("@E has filetype set.\n"),
9199 PROMPT_CLEAR, PR_PREEN_OK },
9201 /* Directory filename is null */
9202 { PR_2_NULL_NAME,
9203 N_("@E has a @z name.\n"),
9204 PROMPT_CLEAR, 0 },
9206 /* Invalid symlink */
9207 { PR_2_INVALID_SYMLINK,
9208 N_("Symlink %Q (@i #%i) is @n.\n"),
9209 PROMPT_CLEAR, 0 },
9211 /* i_file_acl (extended attribute block) is bad */
9212 { PR_2_FILE_ACL_BAD,
9213 N_("@a @b @F @n (%If).\n"),
9214 PROMPT_CLEAR, 0 },
9216 /* Filesystem contains large files, but has no such flag in sb */
9217 { PR_2_FEATURE_LARGE_FILES,
9218 N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
9219 PROMPT_FIX, 0 },
9221 /* Node in HTREE directory not referenced */
9222 { PR_2_HTREE_NOTREF,
9223 N_("@p @h %d: node (%B) not referenced\n"),
9224 PROMPT_NONE, 0 },
9226 /* Node in HTREE directory referenced twice */
9227 { PR_2_HTREE_DUPREF,
9228 N_("@p @h %d: node (%B) referenced twice\n"),
9229 PROMPT_NONE, 0 },
9231 /* Node in HTREE directory has bad min hash */
9232 { PR_2_HTREE_MIN_HASH,
9233 N_("@p @h %d: node (%B) has bad min hash\n"),
9234 PROMPT_NONE, 0 },
9236 /* Node in HTREE directory has bad max hash */
9237 { PR_2_HTREE_MAX_HASH,
9238 N_("@p @h %d: node (%B) has bad max hash\n"),
9239 PROMPT_NONE, 0 },
9241 /* Clear invalid HTREE directory */
9242 { PR_2_HTREE_CLEAR,
9243 N_("@n @h %d (%q). "), PROMPT_CLEAR, 0 },
9245 /* Bad block in htree interior node */
9246 { PR_2_HTREE_BADBLK,
9247 N_("@p @h %d (%q): bad @b number %b.\n"),
9248 PROMPT_CLEAR_HTREE, 0 },
9250 /* Error adjusting EA refcount */
9251 { PR_2_ADJ_EA_REFCOUNT,
9252 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
9253 PROMPT_NONE, PR_FATAL },
9255 /* Invalid HTREE root node */
9256 { PR_2_HTREE_BAD_ROOT,
9257 N_("@p @h %d: root node is @n\n"),
9258 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9260 /* Invalid HTREE limit */
9261 { PR_2_HTREE_BAD_LIMIT,
9262 N_("@p @h %d: node (%B) has @n limit (%N)\n"),
9263 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9265 /* Invalid HTREE count */
9266 { PR_2_HTREE_BAD_COUNT,
9267 N_("@p @h %d: node (%B) has @n count (%N)\n"),
9268 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9270 /* HTREE interior node has out-of-order hashes in table */
9271 { PR_2_HTREE_HASH_ORDER,
9272 N_("@p @h %d: node (%B) has an unordered hash table\n"),
9273 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9275 /* Node in HTREE directory has invalid depth */
9276 { PR_2_HTREE_BAD_DEPTH,
9277 N_("@p @h %d: node (%B) has @n depth\n"),
9278 PROMPT_NONE, 0 },
9280 /* Duplicate directory entry found */
9281 { PR_2_DUPLICATE_DIRENT,
9282 N_("Duplicate @E found. "),
9283 PROMPT_CLEAR, 0 },
9285 /* Non-unique filename found */
9286 { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
9287 N_("@E has a non-unique filename.\nRename to %s"),
9288 PROMPT_NULL, 0 },
9290 /* Duplicate directory entry found */
9291 { PR_2_REPORT_DUP_DIRENT,
9292 N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
9293 PROMPT_NONE, 0 },
9295 /* Pass 3 errors */
9297 /* Pass 3: Checking directory connectivity */
9298 { PR_3_PASS_HEADER,
9299 N_("Pass 3: Checking @d connectivity\n"),
9300 PROMPT_NONE, 0 },
9302 /* Root inode not allocated */
9303 { PR_3_NO_ROOT_INODE,
9304 N_("@r not allocated. "),
9305 PROMPT_ALLOCATE, 0 },
9307 /* No room in lost+found */
9308 { PR_3_EXPAND_LF_DIR,
9309 N_("No room in @l @d. "),
9310 PROMPT_EXPAND, 0 },
9312 /* Unconnected directory inode */
9313 { PR_3_UNCONNECTED_DIR,
9314 N_("Unconnected @d @i %i (%p)\n"),
9315 PROMPT_CONNECT, 0 },
9317 /* /lost+found not found */
9318 { PR_3_NO_LF_DIR,
9319 N_("/@l not found. "),
9320 PROMPT_CREATE, PR_PREEN_OK },
9322 /* .. entry is incorrect */
9323 { PR_3_BAD_DOT_DOT,
9324 N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
9325 PROMPT_FIX, 0 },
9327 /* Bad or non-existent /lost+found. Cannot reconnect */
9328 { PR_3_NO_LPF,
9329 N_("Bad or non-existent /@l. Cannot reconnect.\n"),
9330 PROMPT_NONE, 0 },
9332 /* Could not expand /lost+found */
9333 { PR_3_CANT_EXPAND_LPF,
9334 N_("Could not expand /@l: %m\n"),
9335 PROMPT_NONE, 0 },
9337 /* Could not reconnect inode */
9338 { PR_3_CANT_RECONNECT,
9339 N_("Could not reconnect %i: %m\n"),
9340 PROMPT_NONE, 0 },
9342 /* Error while trying to find /lost+found */
9343 { PR_3_ERR_FIND_LPF,
9344 N_("Error while trying to find /@l: %m\n"),
9345 PROMPT_NONE, 0 },
9347 /* Error in ext2fs_new_block while creating /lost+found */
9348 { PR_3_ERR_LPF_NEW_BLOCK,
9349 N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
9350 PROMPT_NONE, 0 },
9352 /* Error in ext2fs_new_inode while creating /lost+found */
9353 { PR_3_ERR_LPF_NEW_INODE,
9354 N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
9355 PROMPT_NONE, 0 },
9357 /* Error in ext2fs_new_dir_block while creating /lost+found */
9358 { PR_3_ERR_LPF_NEW_DIR_BLOCK,
9359 N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
9360 PROMPT_NONE, 0 },
9362 /* Error while writing directory block for /lost+found */
9363 { PR_3_ERR_LPF_WRITE_BLOCK,
9364 N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
9365 PROMPT_NONE, 0 },
9367 /* Error while adjusting inode count */
9368 { PR_3_ADJUST_INODE,
9369 N_("Error while adjusting @i count on @i %i\n"),
9370 PROMPT_NONE, 0 },
9372 /* Couldn't fix parent directory -- error */
9373 { PR_3_FIX_PARENT_ERR,
9374 N_("Couldn't fix parent of @i %i: %m\n\n"),
9375 PROMPT_NONE, 0 },
9377 /* Couldn't fix parent directory -- couldn't find it */
9378 { PR_3_FIX_PARENT_NOFIND,
9379 N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
9380 PROMPT_NONE, 0 },
9382 /* Error allocating inode bitmap */
9383 { PR_3_ALLOCATE_IBITMAP_ERROR,
9384 N_("@A @i @B (%N): %m\n"),
9385 PROMPT_NONE, PR_FATAL },
9387 /* Error creating root directory */
9388 { PR_3_CREATE_ROOT_ERROR,
9389 N_("Error creating root @d (%s): %m\n"),
9390 PROMPT_NONE, PR_FATAL },
9392 /* Error creating lost and found directory */
9393 { PR_3_CREATE_LPF_ERROR,
9394 N_("Error creating /@l @d (%s): %m\n"),
9395 PROMPT_NONE, PR_FATAL },
9397 /* Root inode is not directory; aborting */
9398 { PR_3_ROOT_NOT_DIR_ABORT,
9399 N_("@r is not a @d; aborting.\n"),
9400 PROMPT_NONE, PR_FATAL },
9402 /* Cannot proceed without a root inode. */
9403 { PR_3_NO_ROOT_INODE_ABORT,
9404 N_("can't proceed without a @r.\n"),
9405 PROMPT_NONE, PR_FATAL },
9407 /* Internal error: couldn't find dir_info */
9408 { PR_3_NO_DIRINFO,
9409 N_("Internal error: cannot find dir_info for %i.\n"),
9410 PROMPT_NONE, PR_FATAL },
9412 /* Lost+found not a directory */
9413 { PR_3_LPF_NOTDIR,
9414 N_("/@l is not a @d (ino=%i)\n"),
9415 PROMPT_UNLINK, 0 },
9417 /* Pass 3A Directory Optimization */
9419 /* Pass 3A: Optimizing directories */
9420 { PR_3A_PASS_HEADER,
9421 N_("Pass 3A: Optimizing directories\n"),
9422 PROMPT_NONE, PR_PREEN_NOMSG },
9424 /* Error iterating over directories */
9425 { PR_3A_OPTIMIZE_ITER,
9426 N_("Failed to create dirs_to_hash iterator: %m"),
9427 PROMPT_NONE, 0 },
9429 /* Error rehash directory */
9430 { PR_3A_OPTIMIZE_DIR_ERR,
9431 N_("Failed to optimize directory %q (%d): %m"),
9432 PROMPT_NONE, 0 },
9434 /* Rehashing dir header */
9435 { PR_3A_OPTIMIZE_DIR_HEADER,
9436 N_("Optimizing directories: "),
9437 PROMPT_NONE, PR_MSG_ONLY },
9439 /* Rehashing directory %d */
9440 { PR_3A_OPTIMIZE_DIR,
9441 " %d",
9442 PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
9444 /* Rehashing dir end */
9445 { PR_3A_OPTIMIZE_DIR_END,
9446 "\n",
9447 PROMPT_NONE, PR_PREEN_NOHDR },
9449 /* Pass 4 errors */
9451 /* Pass 4: Checking reference counts */
9452 { PR_4_PASS_HEADER,
9453 N_("Pass 4: Checking reference counts\n"),
9454 PROMPT_NONE, 0 },
9456 /* Unattached zero-length inode */
9457 { PR_4_ZERO_LEN_INODE,
9458 N_("@u @z @i %i. "),
9459 PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
9461 /* Unattached inode */
9462 { PR_4_UNATTACHED_INODE,
9463 N_("@u @i %i\n"),
9464 PROMPT_CONNECT, 0 },
9466 /* Inode ref count wrong */
9467 { PR_4_BAD_REF_COUNT,
9468 N_("@i %i ref count is %Il, @s %N. "),
9469 PROMPT_FIX, PR_PREEN_OK },
9471 { PR_4_INCONSISTENT_COUNT,
9472 N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
9473 "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
9474 "@i_link_info[%i] is %N, @i.i_links_count is %Il. "
9475 "They @s the same!\n"),
9476 PROMPT_NONE, 0 },
9478 /* Pass 5 errors */
9480 /* Pass 5: Checking group summary information */
9481 { PR_5_PASS_HEADER,
9482 N_("Pass 5: Checking @g summary information\n"),
9483 PROMPT_NONE, 0 },
9485 /* Padding at end of inode bitmap is not set. */
9486 { PR_5_INODE_BMAP_PADDING,
9487 N_("Padding at end of @i @B is not set. "),
9488 PROMPT_FIX, PR_PREEN_OK },
9490 /* Padding at end of block bitmap is not set. */
9491 { PR_5_BLOCK_BMAP_PADDING,
9492 N_("Padding at end of @b @B is not set. "),
9493 PROMPT_FIX, PR_PREEN_OK },
9495 /* Block bitmap differences header */
9496 { PR_5_BLOCK_BITMAP_HEADER,
9497 N_("@b @B differences: "),
9498 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
9500 /* Block not used, but marked in bitmap */
9501 { PR_5_BLOCK_UNUSED,
9502 " -%b",
9503 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9505 /* Block used, but not marked used in bitmap */
9506 { PR_5_BLOCK_USED,
9507 " +%b",
9508 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9510 /* Block bitmap differences end */
9511 { PR_5_BLOCK_BITMAP_END,
9512 "\n",
9513 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9515 /* Inode bitmap differences header */
9516 { PR_5_INODE_BITMAP_HEADER,
9517 N_("@i @B differences: "),
9518 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9520 /* Inode not used, but marked in bitmap */
9521 { PR_5_INODE_UNUSED,
9522 " -%i",
9523 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9525 /* Inode used, but not marked used in bitmap */
9526 { PR_5_INODE_USED,
9527 " +%i",
9528 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9530 /* Inode bitmap differences end */
9531 { PR_5_INODE_BITMAP_END,
9532 "\n",
9533 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9535 /* Free inodes count for group wrong */
9536 { PR_5_FREE_INODE_COUNT_GROUP,
9537 N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
9538 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9540 /* Directories count for group wrong */
9541 { PR_5_FREE_DIR_COUNT_GROUP,
9542 N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
9543 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9545 /* Free inodes count wrong */
9546 { PR_5_FREE_INODE_COUNT,
9547 N_("Free @is count wrong (%i, counted=%j).\n"),
9548 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9550 /* Free blocks count for group wrong */
9551 { PR_5_FREE_BLOCK_COUNT_GROUP,
9552 N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
9553 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9555 /* Free blocks count wrong */
9556 { PR_5_FREE_BLOCK_COUNT,
9557 N_("Free @bs count wrong (%b, counted=%c).\n"),
9558 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9560 /* Programming error: bitmap endpoints don't match */
9561 { PR_5_BMAP_ENDPOINTS,
9562 N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
9563 "match calculated @B endpoints (%i, %j)\n"),
9564 PROMPT_NONE, PR_FATAL },
9566 /* Internal error: fudging end of bitmap */
9567 { PR_5_FUDGE_BITMAP_ERROR,
9568 N_("Internal error: fudging end of bitmap (%N)\n"),
9569 PROMPT_NONE, PR_FATAL },
9571 /* Error copying in replacement inode bitmap */
9572 { PR_5_COPY_IBITMAP_ERROR,
9573 N_("Error copying in replacement @i @B: %m\n"),
9574 PROMPT_NONE, PR_FATAL },
9576 /* Error copying in replacement block bitmap */
9577 { PR_5_COPY_BBITMAP_ERROR,
9578 N_("Error copying in replacement @b @B: %m\n"),
9579 PROMPT_NONE, PR_FATAL },
9581 /* Block range not used, but marked in bitmap */
9582 { PR_5_BLOCK_RANGE_UNUSED,
9583 " -(%b--%c)",
9584 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9586 /* Block range used, but not marked used in bitmap */
9587 { PR_5_BLOCK_RANGE_USED,
9588 " +(%b--%c)",
9589 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9591 /* Inode range not used, but marked in bitmap */
9592 { PR_5_INODE_RANGE_UNUSED,
9593 " -(%i--%j)",
9594 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9596 /* Inode range used, but not marked used in bitmap */
9597 { PR_5_INODE_RANGE_USED,
9598 " +(%i--%j)",
9599 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9601 { 0 }
9605 * This is the latch flags register. It allows several problems to be
9606 * "latched" together. This means that the user has to answer but one
9607 * question for the set of problems, and all of the associated
9608 * problems will be either fixed or not fixed.
9610 static struct latch_descr pr_latch_info[] = {
9611 { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
9612 { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
9613 { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
9614 { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
9615 { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
9616 { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
9617 { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
9618 { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
9619 { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
9620 { -1, 0, 0 },
9623 static const struct e2fsck_problem *find_problem(problem_t code)
9625 int i;
9627 for (i=0; problem_table[i].e2p_code; i++) {
9628 if (problem_table[i].e2p_code == code)
9629 return &problem_table[i];
9631 return 0;
9634 static struct latch_descr *find_latch(int code)
9636 int i;
9638 for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
9639 if (pr_latch_info[i].latch_code == code)
9640 return &pr_latch_info[i];
9642 return 0;
9645 int end_problem_latch(e2fsck_t ctx, int mask)
9647 struct latch_descr *ldesc;
9648 struct problem_context pctx;
9649 int answer = -1;
9651 ldesc = find_latch(mask);
9652 if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
9653 clear_problem_context(&pctx);
9654 answer = fix_problem(ctx, ldesc->end_message, &pctx);
9656 ldesc->flags &= ~(PRL_VARIABLE);
9657 return answer;
9660 int set_latch_flags(int mask, int setflags, int clearflags)
9662 struct latch_descr *ldesc;
9664 ldesc = find_latch(mask);
9665 if (!ldesc)
9666 return -1;
9667 ldesc->flags |= setflags;
9668 ldesc->flags &= ~clearflags;
9669 return 0;
9672 void clear_problem_context(struct problem_context *ctx)
9674 memset(ctx, 0, sizeof(struct problem_context));
9675 ctx->blkcount = -1;
9676 ctx->group = -1;
9679 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
9681 ext2_filsys fs = ctx->fs;
9682 const struct e2fsck_problem *ptr;
9683 struct latch_descr *ldesc = NULL;
9684 const char *message;
9685 int def_yn, answer, ans;
9686 int print_answer = 0;
9687 int suppress = 0;
9689 ptr = find_problem(code);
9690 if (!ptr) {
9691 printf(_("Unhandled error code (0x%x)!\n"), code);
9692 return 0;
9694 def_yn = 1;
9695 if ((ptr->flags & PR_NO_DEFAULT) ||
9696 ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
9697 (ctx->options & E2F_OPT_NO))
9698 def_yn= 0;
9701 * Do special latch processing. This is where we ask the
9702 * latch question, if it exists
9704 if (ptr->flags & PR_LATCH_MASK) {
9705 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
9706 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
9707 ans = fix_problem(ctx, ldesc->question, pctx);
9708 if (ans == 1)
9709 ldesc->flags |= PRL_YES;
9710 if (ans == 0)
9711 ldesc->flags |= PRL_NO;
9712 ldesc->flags |= PRL_LATCHED;
9714 if (ldesc->flags & PRL_SUPPRESS)
9715 suppress++;
9717 if ((ptr->flags & PR_PREEN_NOMSG) &&
9718 (ctx->options & E2F_OPT_PREEN))
9719 suppress++;
9720 if ((ptr->flags & PR_NO_NOMSG) &&
9721 (ctx->options & E2F_OPT_NO))
9722 suppress++;
9723 if (!suppress) {
9724 message = ptr->e2p_description;
9725 if ((ctx->options & E2F_OPT_PREEN) &&
9726 !(ptr->flags & PR_PREEN_NOHDR)) {
9727 printf("%s: ", ctx->device_name ?
9728 ctx->device_name : ctx->filesystem_name);
9730 if (*message)
9731 print_e2fsck_message(ctx, _(message), pctx, 1);
9733 if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
9734 preenhalt(ctx);
9736 if (ptr->flags & PR_FATAL)
9737 bb_error_msg_and_die(0);
9739 if (ptr->prompt == PROMPT_NONE) {
9740 if (ptr->flags & PR_NOCOLLATE)
9741 answer = -1;
9742 else
9743 answer = def_yn;
9744 } else {
9745 if (ctx->options & E2F_OPT_PREEN) {
9746 answer = def_yn;
9747 if (!(ptr->flags & PR_PREEN_NOMSG))
9748 print_answer = 1;
9749 } else if ((ptr->flags & PR_LATCH_MASK) &&
9750 (ldesc->flags & (PRL_YES | PRL_NO))) {
9751 if (!suppress)
9752 print_answer = 1;
9753 if (ldesc->flags & PRL_YES)
9754 answer = 1;
9755 else
9756 answer = 0;
9757 } else
9758 answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
9759 if (!answer && !(ptr->flags & PR_NO_OK))
9760 ext2fs_unmark_valid(fs);
9762 if (print_answer)
9763 printf("%s.\n", answer ?
9764 _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
9767 if ((ptr->prompt == PROMPT_ABORT) && answer)
9768 bb_error_msg_and_die(0);
9770 if (ptr->flags & PR_AFTER_CODE)
9771 answer = fix_problem(ctx, ptr->second_code, pctx);
9773 return answer;
9777 * linux/fs/recovery.c
9779 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
9783 * Maintain information about the progress of the recovery job, so that
9784 * the different passes can carry information between them.
9786 struct recovery_info
9788 tid_t start_transaction;
9789 tid_t end_transaction;
9791 int nr_replays;
9792 int nr_revokes;
9793 int nr_revoke_hits;
9796 enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
9797 static int do_one_pass(journal_t *journal,
9798 struct recovery_info *info, enum passtype pass);
9799 static int scan_revoke_records(journal_t *, struct buffer_head *,
9800 tid_t, struct recovery_info *);
9803 * Read a block from the journal
9806 static int jread(struct buffer_head **bhp, journal_t *journal,
9807 unsigned int offset)
9809 int err;
9810 unsigned long blocknr;
9811 struct buffer_head *bh;
9813 *bhp = NULL;
9815 err = journal_bmap(journal, offset, &blocknr);
9817 if (err) {
9818 printf("JBD: bad block at offset %u\n", offset);
9819 return err;
9822 bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
9823 if (!bh)
9824 return -ENOMEM;
9826 if (!buffer_uptodate(bh)) {
9827 /* If this is a brand new buffer, start readahead.
9828 Otherwise, we assume we are already reading it. */
9829 if (!buffer_req(bh))
9830 do_readahead(journal, offset);
9831 wait_on_buffer(bh);
9834 if (!buffer_uptodate(bh)) {
9835 printf("JBD: Failed to read block at offset %u\n", offset);
9836 brelse(bh);
9837 return -EIO;
9840 *bhp = bh;
9841 return 0;
9846 * Count the number of in-use tags in a journal descriptor block.
9849 static int count_tags(struct buffer_head *bh, int size)
9851 char * tagp;
9852 journal_block_tag_t * tag;
9853 int nr = 0;
9855 tagp = &bh->b_data[sizeof(journal_header_t)];
9857 while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
9858 tag = (journal_block_tag_t *) tagp;
9860 nr++;
9861 tagp += sizeof(journal_block_tag_t);
9862 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
9863 tagp += 16;
9865 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
9866 break;
9869 return nr;
9873 /* Make sure we wrap around the log correctly! */
9874 #define wrap(journal, var) \
9875 do { \
9876 if (var >= (journal)->j_last) \
9877 var -= ((journal)->j_last - (journal)->j_first); \
9878 } while (0)
9881 * int journal_recover(journal_t *journal) - recovers a on-disk journal
9882 * @journal: the journal to recover
9884 * The primary function for recovering the log contents when mounting a
9885 * journaled device.
9887 * Recovery is done in three passes. In the first pass, we look for the
9888 * end of the log. In the second, we assemble the list of revoke
9889 * blocks. In the third and final pass, we replay any un-revoked blocks
9890 * in the log.
9892 int journal_recover(journal_t *journal)
9894 int err;
9895 journal_superblock_t * sb;
9897 struct recovery_info info;
9899 memset(&info, 0, sizeof(info));
9900 sb = journal->j_superblock;
9903 * The journal superblock's s_start field (the current log head)
9904 * is always zero if, and only if, the journal was cleanly
9905 * unmounted.
9908 if (!sb->s_start) {
9909 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
9910 return 0;
9913 err = do_one_pass(journal, &info, PASS_SCAN);
9914 if (!err)
9915 err = do_one_pass(journal, &info, PASS_REVOKE);
9916 if (!err)
9917 err = do_one_pass(journal, &info, PASS_REPLAY);
9919 /* Restart the log at the next transaction ID, thus invalidating
9920 * any existing commit records in the log. */
9921 journal->j_transaction_sequence = ++info.end_transaction;
9923 journal_clear_revoke(journal);
9924 sync_blockdev(journal->j_fs_dev);
9925 return err;
9928 static int do_one_pass(journal_t *journal,
9929 struct recovery_info *info, enum passtype pass)
9931 unsigned int first_commit_ID, next_commit_ID;
9932 unsigned long next_log_block;
9933 int err, success = 0;
9934 journal_superblock_t * sb;
9935 journal_header_t * tmp;
9936 struct buffer_head * bh;
9937 unsigned int sequence;
9938 int blocktype;
9940 /* Precompute the maximum metadata descriptors in a descriptor block */
9941 int MAX_BLOCKS_PER_DESC;
9942 MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
9943 / sizeof(journal_block_tag_t));
9946 * First thing is to establish what we expect to find in the log
9947 * (in terms of transaction IDs), and where (in terms of log
9948 * block offsets): query the superblock.
9951 sb = journal->j_superblock;
9952 next_commit_ID = ntohl(sb->s_sequence);
9953 next_log_block = ntohl(sb->s_start);
9955 first_commit_ID = next_commit_ID;
9956 if (pass == PASS_SCAN)
9957 info->start_transaction = first_commit_ID;
9960 * Now we walk through the log, transaction by transaction,
9961 * making sure that each transaction has a commit block in the
9962 * expected place. Each complete transaction gets replayed back
9963 * into the main filesystem.
9966 while (1) {
9967 int flags;
9968 char * tagp;
9969 journal_block_tag_t * tag;
9970 struct buffer_head * obh;
9971 struct buffer_head * nbh;
9973 /* If we already know where to stop the log traversal,
9974 * check right now that we haven't gone past the end of
9975 * the log. */
9977 if (pass != PASS_SCAN)
9978 if (tid_geq(next_commit_ID, info->end_transaction))
9979 break;
9981 /* Skip over each chunk of the transaction looking
9982 * either the next descriptor block or the final commit
9983 * record. */
9985 err = jread(&bh, journal, next_log_block);
9986 if (err)
9987 goto failed;
9989 next_log_block++;
9990 wrap(journal, next_log_block);
9992 /* What kind of buffer is it?
9994 * If it is a descriptor block, check that it has the
9995 * expected sequence number. Otherwise, we're all done
9996 * here. */
9998 tmp = (journal_header_t *)bh->b_data;
10000 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
10001 brelse(bh);
10002 break;
10005 blocktype = ntohl(tmp->h_blocktype);
10006 sequence = ntohl(tmp->h_sequence);
10008 if (sequence != next_commit_ID) {
10009 brelse(bh);
10010 break;
10013 /* OK, we have a valid descriptor block which matches
10014 * all of the sequence number checks. What are we going
10015 * to do with it? That depends on the pass... */
10017 switch (blocktype) {
10018 case JFS_DESCRIPTOR_BLOCK:
10019 /* If it is a valid descriptor block, replay it
10020 * in pass REPLAY; otherwise, just skip over the
10021 * blocks it describes. */
10022 if (pass != PASS_REPLAY) {
10023 next_log_block +=
10024 count_tags(bh, journal->j_blocksize);
10025 wrap(journal, next_log_block);
10026 brelse(bh);
10027 continue;
10030 /* A descriptor block: we can now write all of
10031 * the data blocks. Yay, useful work is finally
10032 * getting done here! */
10034 tagp = &bh->b_data[sizeof(journal_header_t)];
10035 while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
10036 <= journal->j_blocksize) {
10037 unsigned long io_block;
10039 tag = (journal_block_tag_t *) tagp;
10040 flags = ntohl(tag->t_flags);
10042 io_block = next_log_block++;
10043 wrap(journal, next_log_block);
10044 err = jread(&obh, journal, io_block);
10045 if (err) {
10046 /* Recover what we can, but
10047 * report failure at the end. */
10048 success = err;
10049 printf("JBD: IO error %d recovering "
10050 "block %ld in log\n",
10051 err, io_block);
10052 } else {
10053 unsigned long blocknr;
10055 blocknr = ntohl(tag->t_blocknr);
10057 /* If the block has been
10058 * revoked, then we're all done
10059 * here. */
10060 if (journal_test_revoke
10061 (journal, blocknr,
10062 next_commit_ID)) {
10063 brelse(obh);
10064 ++info->nr_revoke_hits;
10065 goto skip_write;
10068 /* Find a buffer for the new
10069 * data being restored */
10070 nbh = getblk(journal->j_fs_dev,
10071 blocknr,
10072 journal->j_blocksize);
10073 if (nbh == NULL) {
10074 printf("JBD: Out of memory "
10075 "during recovery.\n");
10076 err = -ENOMEM;
10077 brelse(bh);
10078 brelse(obh);
10079 goto failed;
10082 lock_buffer(nbh);
10083 memcpy(nbh->b_data, obh->b_data,
10084 journal->j_blocksize);
10085 if (flags & JFS_FLAG_ESCAPE) {
10086 *((unsigned int *)bh->b_data) =
10087 htonl(JFS_MAGIC_NUMBER);
10090 mark_buffer_uptodate(nbh, 1);
10091 mark_buffer_dirty(nbh);
10092 ++info->nr_replays;
10093 /* ll_rw_block(WRITE, 1, &nbh); */
10094 unlock_buffer(nbh);
10095 brelse(obh);
10096 brelse(nbh);
10099 skip_write:
10100 tagp += sizeof(journal_block_tag_t);
10101 if (!(flags & JFS_FLAG_SAME_UUID))
10102 tagp += 16;
10104 if (flags & JFS_FLAG_LAST_TAG)
10105 break;
10108 brelse(bh);
10109 continue;
10111 case JFS_COMMIT_BLOCK:
10112 /* Found an expected commit block: not much to
10113 * do other than move on to the next sequence
10114 * number. */
10115 brelse(bh);
10116 next_commit_ID++;
10117 continue;
10119 case JFS_REVOKE_BLOCK:
10120 /* If we aren't in the REVOKE pass, then we can
10121 * just skip over this block. */
10122 if (pass != PASS_REVOKE) {
10123 brelse(bh);
10124 continue;
10127 err = scan_revoke_records(journal, bh,
10128 next_commit_ID, info);
10129 brelse(bh);
10130 if (err)
10131 goto failed;
10132 continue;
10134 default:
10135 goto done;
10139 done:
10141 * We broke out of the log scan loop: either we came to the
10142 * known end of the log or we found an unexpected block in the
10143 * log. If the latter happened, then we know that the "current"
10144 * transaction marks the end of the valid log.
10147 if (pass == PASS_SCAN)
10148 info->end_transaction = next_commit_ID;
10149 else {
10150 /* It's really bad news if different passes end up at
10151 * different places (but possible due to IO errors). */
10152 if (info->end_transaction != next_commit_ID) {
10153 printf("JBD: recovery pass %d ended at "
10154 "transaction %u, expected %u\n",
10155 pass, next_commit_ID, info->end_transaction);
10156 if (!success)
10157 success = -EIO;
10161 return success;
10163 failed:
10164 return err;
10168 /* Scan a revoke record, marking all blocks mentioned as revoked. */
10170 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
10171 tid_t sequence, struct recovery_info *info)
10173 journal_revoke_header_t *header;
10174 int offset, max;
10176 header = (journal_revoke_header_t *) bh->b_data;
10177 offset = sizeof(journal_revoke_header_t);
10178 max = ntohl(header->r_count);
10180 while (offset < max) {
10181 unsigned long blocknr;
10182 int err;
10184 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
10185 offset += 4;
10186 err = journal_set_revoke(journal, blocknr, sequence);
10187 if (err)
10188 return err;
10189 ++info->nr_revokes;
10191 return 0;
10196 * rehash.c --- rebuild hash tree directories
10198 * This algorithm is designed for simplicity of implementation and to
10199 * pack the directory as much as possible. It however requires twice
10200 * as much memory as the size of the directory. The maximum size
10201 * directory supported using a 4k blocksize is roughly a gigabyte, and
10202 * so there may very well be problems with machines that don't have
10203 * virtual memory, and obscenely large directories.
10205 * An alternate algorithm which is much more disk intensive could be
10206 * written, and probably will need to be written in the future. The
10207 * design goals of such an algorithm are: (a) use (roughly) constant
10208 * amounts of memory, no matter how large the directory, (b) the
10209 * directory must be safe at all times, even if e2fsck is interrupted
10210 * in the middle, (c) we must use minimal amounts of extra disk
10211 * blocks. This pretty much requires an incremental approach, where
10212 * we are reading from one part of the directory, and inserting into
10213 * the front half. So the algorithm will have to keep track of a
10214 * moving block boundary between the new tree and the old tree, and
10215 * files will need to be moved from the old directory and inserted
10216 * into the new tree. If the new directory requires space which isn't
10217 * yet available, blocks from the beginning part of the old directory
10218 * may need to be moved to the end of the directory to make room for
10219 * the new tree:
10221 * --------------------------------------------------------
10222 * | new tree | | old tree |
10223 * --------------------------------------------------------
10224 * ^ ptr ^ptr
10225 * tail new head old
10227 * This is going to be a pain in the tuckus to implement, and will
10228 * require a lot more disk accesses. So I'm going to skip it for now;
10229 * it's only really going to be an issue for really, really big
10230 * filesystems (when we reach the level of tens of millions of files
10231 * in a single directory). It will probably be easier to simply
10232 * require that e2fsck use VM first.
10235 struct fill_dir_struct {
10236 char *buf;
10237 struct ext2_inode *inode;
10238 int err;
10239 e2fsck_t ctx;
10240 struct hash_entry *harray;
10241 int max_array, num_array;
10242 int dir_size;
10243 int compress;
10244 ino_t parent;
10247 struct hash_entry {
10248 ext2_dirhash_t hash;
10249 ext2_dirhash_t minor_hash;
10250 struct ext2_dir_entry *dir;
10253 struct out_dir {
10254 int num;
10255 int max;
10256 char *buf;
10257 ext2_dirhash_t *hashes;
10260 static int fill_dir_block(ext2_filsys fs,
10261 blk_t *block_nr,
10262 e2_blkcnt_t blockcnt,
10263 blk_t ref_block FSCK_ATTR((unused)),
10264 int ref_offset FSCK_ATTR((unused)),
10265 void *priv_data)
10267 struct fill_dir_struct *fd = (struct fill_dir_struct *) priv_data;
10268 struct hash_entry *new_array, *ent;
10269 struct ext2_dir_entry *dirent;
10270 char *dir;
10271 unsigned int offset, dir_offset;
10273 if (blockcnt < 0)
10274 return 0;
10276 offset = blockcnt * fs->blocksize;
10277 if (offset + fs->blocksize > fd->inode->i_size) {
10278 fd->err = EXT2_ET_DIR_CORRUPTED;
10279 return BLOCK_ABORT;
10281 dir = (fd->buf+offset);
10282 if (HOLE_BLKADDR(*block_nr)) {
10283 memset(dir, 0, fs->blocksize);
10284 dirent = (struct ext2_dir_entry *) dir;
10285 dirent->rec_len = fs->blocksize;
10286 } else {
10287 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
10288 if (fd->err)
10289 return BLOCK_ABORT;
10291 /* While the directory block is "hot", index it. */
10292 dir_offset = 0;
10293 while (dir_offset < fs->blocksize) {
10294 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
10295 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
10296 (dirent->rec_len < 8) ||
10297 ((dirent->rec_len % 4) != 0) ||
10298 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
10299 fd->err = EXT2_ET_DIR_CORRUPTED;
10300 return BLOCK_ABORT;
10302 dir_offset += dirent->rec_len;
10303 if (dirent->inode == 0)
10304 continue;
10305 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
10306 (dirent->name[0] == '.'))
10307 continue;
10308 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
10309 (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
10310 fd->parent = dirent->inode;
10311 continue;
10313 if (fd->num_array >= fd->max_array) {
10314 new_array = xrealloc(fd->harray,
10315 sizeof(struct hash_entry) * (fd->max_array+500));
10316 fd->harray = new_array;
10317 fd->max_array += 500;
10319 ent = fd->harray + fd->num_array++;
10320 ent->dir = dirent;
10321 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
10322 if (fd->compress)
10323 ent->hash = ent->minor_hash = 0;
10324 else {
10325 fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
10326 dirent->name,
10327 dirent->name_len & 0xFF,
10328 fs->super->s_hash_seed,
10329 &ent->hash, &ent->minor_hash);
10330 if (fd->err)
10331 return BLOCK_ABORT;
10335 return 0;
10338 /* Used for sorting the hash entry */
10339 static int name_cmp(const void *a, const void *b)
10341 const struct hash_entry *he_a = (const struct hash_entry *) a;
10342 const struct hash_entry *he_b = (const struct hash_entry *) b;
10343 int ret;
10344 int min_len;
10346 min_len = he_a->dir->name_len;
10347 if (min_len > he_b->dir->name_len)
10348 min_len = he_b->dir->name_len;
10350 ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
10351 if (ret == 0) {
10352 if (he_a->dir->name_len > he_b->dir->name_len)
10353 ret = 1;
10354 else if (he_a->dir->name_len < he_b->dir->name_len)
10355 ret = -1;
10356 else
10357 ret = he_b->dir->inode - he_a->dir->inode;
10359 return ret;
10362 /* Used for sorting the hash entry */
10363 static int hash_cmp(const void *a, const void *b)
10365 const struct hash_entry *he_a = (const struct hash_entry *) a;
10366 const struct hash_entry *he_b = (const struct hash_entry *) b;
10367 int ret;
10369 if (he_a->hash > he_b->hash)
10370 ret = 1;
10371 else if (he_a->hash < he_b->hash)
10372 ret = -1;
10373 else {
10374 if (he_a->minor_hash > he_b->minor_hash)
10375 ret = 1;
10376 else if (he_a->minor_hash < he_b->minor_hash)
10377 ret = -1;
10378 else
10379 ret = name_cmp(a, b);
10381 return ret;
10384 static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
10385 int blocks)
10387 void *new_mem;
10389 if (outdir->max) {
10390 new_mem = xrealloc(outdir->buf, blocks * fs->blocksize);
10391 outdir->buf = new_mem;
10392 new_mem = xrealloc(outdir->hashes,
10393 blocks * sizeof(ext2_dirhash_t));
10394 outdir->hashes = new_mem;
10395 } else {
10396 outdir->buf = xmalloc(blocks * fs->blocksize);
10397 outdir->hashes = xmalloc(blocks * sizeof(ext2_dirhash_t));
10398 outdir->num = 0;
10400 outdir->max = blocks;
10401 return 0;
10404 static void free_out_dir(struct out_dir *outdir)
10406 free(outdir->buf);
10407 free(outdir->hashes);
10408 outdir->max = 0;
10409 outdir->num =0;
10412 static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
10413 char ** ret)
10415 errcode_t retval;
10417 if (outdir->num >= outdir->max) {
10418 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
10419 if (retval)
10420 return retval;
10422 *ret = outdir->buf + (outdir->num++ * fs->blocksize);
10423 memset(*ret, 0, fs->blocksize);
10424 return 0;
10428 * This function is used to make a unique filename. We do this by
10429 * appending ~0, and then incrementing the number. However, we cannot
10430 * expand the length of the filename beyond the padding available in
10431 * the directory entry.
10433 static void mutate_name(char *str, __u16 *len)
10435 int i;
10436 __u16 l = *len & 0xFF, h = *len & 0xff00;
10439 * First check to see if it looks the name has been mutated
10440 * already
10442 for (i = l-1; i > 0; i--) {
10443 if (!isdigit(str[i]))
10444 break;
10446 if ((i == l-1) || (str[i] != '~')) {
10447 if (((l-1) & 3) < 2)
10448 l += 2;
10449 else
10450 l = (l+3) & ~3;
10451 str[l-2] = '~';
10452 str[l-1] = '0';
10453 *len = l | h;
10454 return;
10456 for (i = l-1; i >= 0; i--) {
10457 if (isdigit(str[i])) {
10458 if (str[i] == '9')
10459 str[i] = '0';
10460 else {
10461 str[i]++;
10462 return;
10464 continue;
10466 if (i == 1) {
10467 if (str[0] == 'z')
10468 str[0] = 'A';
10469 else if (str[0] == 'Z') {
10470 str[0] = '~';
10471 str[1] = '0';
10472 } else
10473 str[0]++;
10474 } else if (i > 0) {
10475 str[i] = '1';
10476 str[i-1] = '~';
10477 } else {
10478 if (str[0] == '~')
10479 str[0] = 'a';
10480 else
10481 str[0]++;
10483 break;
10487 static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
10488 ext2_ino_t ino,
10489 struct fill_dir_struct *fd)
10491 struct problem_context pctx;
10492 struct hash_entry *ent, *prev;
10493 int i, j;
10494 int fixed = 0;
10495 char new_name[256];
10496 __u16 new_len;
10498 clear_problem_context(&pctx);
10499 pctx.ino = ino;
10501 for (i=1; i < fd->num_array; i++) {
10502 ent = fd->harray + i;
10503 prev = ent - 1;
10504 if (!ent->dir->inode ||
10505 ((ent->dir->name_len & 0xFF) !=
10506 (prev->dir->name_len & 0xFF)) ||
10507 (strncmp(ent->dir->name, prev->dir->name,
10508 ent->dir->name_len & 0xFF)))
10509 continue;
10510 pctx.dirent = ent->dir;
10511 if ((ent->dir->inode == prev->dir->inode) &&
10512 fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
10513 e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
10514 ent->dir->inode = 0;
10515 fixed++;
10516 continue;
10518 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
10519 new_len = ent->dir->name_len;
10520 mutate_name(new_name, &new_len);
10521 for (j=0; j < fd->num_array; j++) {
10522 if ((i==j) ||
10523 ((ent->dir->name_len & 0xFF) !=
10524 (fd->harray[j].dir->name_len & 0xFF)) ||
10525 (strncmp(new_name, fd->harray[j].dir->name,
10526 new_len & 0xFF)))
10527 continue;
10528 mutate_name(new_name, &new_len);
10530 j = -1;
10532 new_name[new_len & 0xFF] = 0;
10533 pctx.str = new_name;
10534 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
10535 memcpy(ent->dir->name, new_name, new_len & 0xFF);
10536 ent->dir->name_len = new_len;
10537 ext2fs_dirhash(fs->super->s_def_hash_version,
10538 ent->dir->name,
10539 ent->dir->name_len & 0xFF,
10540 fs->super->s_hash_seed,
10541 &ent->hash, &ent->minor_hash);
10542 fixed++;
10545 return fixed;
10549 static errcode_t copy_dir_entries(ext2_filsys fs,
10550 struct fill_dir_struct *fd,
10551 struct out_dir *outdir)
10553 errcode_t retval;
10554 char *block_start;
10555 struct hash_entry *ent;
10556 struct ext2_dir_entry *dirent;
10557 int i, rec_len, left;
10558 ext2_dirhash_t prev_hash;
10559 int offset;
10561 outdir->max = 0;
10562 retval = alloc_size_dir(fs, outdir,
10563 (fd->dir_size / fs->blocksize) + 2);
10564 if (retval)
10565 return retval;
10566 outdir->num = fd->compress ? 0 : 1;
10567 offset = 0;
10568 outdir->hashes[0] = 0;
10569 prev_hash = 1;
10570 if ((retval = get_next_block(fs, outdir, &block_start)))
10571 return retval;
10572 dirent = (struct ext2_dir_entry *) block_start;
10573 left = fs->blocksize;
10574 for (i=0; i < fd->num_array; i++) {
10575 ent = fd->harray + i;
10576 if (ent->dir->inode == 0)
10577 continue;
10578 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
10579 if (rec_len > left) {
10580 if (left)
10581 dirent->rec_len += left;
10582 if ((retval = get_next_block(fs, outdir,
10583 &block_start)))
10584 return retval;
10585 offset = 0;
10587 left = fs->blocksize - offset;
10588 dirent = (struct ext2_dir_entry *) (block_start + offset);
10589 if (offset == 0) {
10590 if (ent->hash == prev_hash)
10591 outdir->hashes[outdir->num-1] = ent->hash | 1;
10592 else
10593 outdir->hashes[outdir->num-1] = ent->hash;
10595 dirent->inode = ent->dir->inode;
10596 dirent->name_len = ent->dir->name_len;
10597 dirent->rec_len = rec_len;
10598 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
10599 offset += rec_len;
10600 left -= rec_len;
10601 if (left < 12) {
10602 dirent->rec_len += left;
10603 offset += left;
10604 left = 0;
10606 prev_hash = ent->hash;
10608 if (left)
10609 dirent->rec_len += left;
10611 return 0;
10615 static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
10616 ext2_ino_t ino, ext2_ino_t parent)
10618 struct ext2_dir_entry *dir;
10619 struct ext2_dx_root_info *root;
10620 struct ext2_dx_countlimit *limits;
10621 int filetype = 0;
10623 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
10624 filetype = EXT2_FT_DIR << 8;
10626 memset(buf, 0, fs->blocksize);
10627 dir = (struct ext2_dir_entry *) buf;
10628 dir->inode = ino;
10629 dir->name[0] = '.';
10630 dir->name_len = 1 | filetype;
10631 dir->rec_len = 12;
10632 dir = (struct ext2_dir_entry *) (buf + 12);
10633 dir->inode = parent;
10634 dir->name[0] = '.';
10635 dir->name[1] = '.';
10636 dir->name_len = 2 | filetype;
10637 dir->rec_len = fs->blocksize - 12;
10639 root = (struct ext2_dx_root_info *) (buf+24);
10640 root->reserved_zero = 0;
10641 root->hash_version = fs->super->s_def_hash_version;
10642 root->info_length = 8;
10643 root->indirect_levels = 0;
10644 root->unused_flags = 0;
10646 limits = (struct ext2_dx_countlimit *) (buf+32);
10647 limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
10648 limits->count = 0;
10650 return root;
10654 static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
10656 struct ext2_dir_entry *dir;
10657 struct ext2_dx_countlimit *limits;
10659 memset(buf, 0, fs->blocksize);
10660 dir = (struct ext2_dir_entry *) buf;
10661 dir->inode = 0;
10662 dir->rec_len = fs->blocksize;
10664 limits = (struct ext2_dx_countlimit *) (buf+8);
10665 limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
10666 limits->count = 0;
10668 return (struct ext2_dx_entry *) limits;
10672 * This function takes the leaf nodes which have been written in
10673 * outdir, and populates the root node and any necessary interior nodes.
10675 static errcode_t calculate_tree(ext2_filsys fs,
10676 struct out_dir *outdir,
10677 ext2_ino_t ino,
10678 ext2_ino_t parent)
10680 struct ext2_dx_root_info *root_info;
10681 struct ext2_dx_entry *root, *dx_ent = NULL;
10682 struct ext2_dx_countlimit *root_limit, *limit;
10683 errcode_t retval;
10684 char * block_start;
10685 int i, c1, c2, nblks;
10686 int limit_offset, root_offset;
10688 root_info = set_root_node(fs, outdir->buf, ino, parent);
10689 root_offset = limit_offset = ((char *) root_info - outdir->buf) +
10690 root_info->info_length;
10691 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10692 c1 = root_limit->limit;
10693 nblks = outdir->num;
10695 /* Write out the pointer blocks */
10696 if (nblks-1 <= c1) {
10697 /* Just write out the root block, and we're done */
10698 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
10699 for (i=1; i < nblks; i++) {
10700 root->block = ext2fs_cpu_to_le32(i);
10701 if (i != 1)
10702 root->hash =
10703 ext2fs_cpu_to_le32(outdir->hashes[i]);
10704 root++;
10705 c1--;
10707 } else {
10708 c2 = 0;
10709 limit = 0;
10710 root_info->indirect_levels = 1;
10711 for (i=1; i < nblks; i++) {
10712 if (c1 == 0)
10713 return ENOSPC;
10714 if (c2 == 0) {
10715 if (limit)
10716 limit->limit = limit->count =
10717 ext2fs_cpu_to_le16(limit->limit);
10718 root = (struct ext2_dx_entry *)
10719 (outdir->buf + root_offset);
10720 root->block = ext2fs_cpu_to_le32(outdir->num);
10721 if (i != 1)
10722 root->hash =
10723 ext2fs_cpu_to_le32(outdir->hashes[i]);
10724 if ((retval = get_next_block(fs, outdir,
10725 &block_start)))
10726 return retval;
10727 dx_ent = set_int_node(fs, block_start);
10728 limit = (struct ext2_dx_countlimit *) dx_ent;
10729 c2 = limit->limit;
10730 root_offset += sizeof(struct ext2_dx_entry);
10731 c1--;
10733 dx_ent->block = ext2fs_cpu_to_le32(i);
10734 if (c2 != limit->limit)
10735 dx_ent->hash =
10736 ext2fs_cpu_to_le32(outdir->hashes[i]);
10737 dx_ent++;
10738 c2--;
10740 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
10741 limit->limit = ext2fs_cpu_to_le16(limit->limit);
10743 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10744 root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
10745 root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
10747 return 0;
10750 struct write_dir_struct {
10751 struct out_dir *outdir;
10752 errcode_t err;
10753 e2fsck_t ctx;
10754 int cleared;
10758 * Helper function which writes out a directory block.
10760 static int write_dir_block(ext2_filsys fs,
10761 blk_t *block_nr,
10762 e2_blkcnt_t blockcnt,
10763 blk_t ref_block FSCK_ATTR((unused)),
10764 int ref_offset FSCK_ATTR((unused)),
10765 void *priv_data)
10767 struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
10768 blk_t blk;
10769 char *dir;
10771 if (*block_nr == 0)
10772 return 0;
10773 if (blockcnt >= wd->outdir->num) {
10774 e2fsck_read_bitmaps(wd->ctx);
10775 blk = *block_nr;
10776 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
10777 ext2fs_block_alloc_stats(fs, blk, -1);
10778 *block_nr = 0;
10779 wd->cleared++;
10780 return BLOCK_CHANGED;
10782 if (blockcnt < 0)
10783 return 0;
10785 dir = wd->outdir->buf + (blockcnt * fs->blocksize);
10786 wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
10787 if (wd->err)
10788 return BLOCK_ABORT;
10789 return 0;
10792 static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
10793 struct out_dir *outdir,
10794 ext2_ino_t ino, int compress)
10796 struct write_dir_struct wd;
10797 errcode_t retval;
10798 struct ext2_inode inode;
10800 retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
10801 if (retval)
10802 return retval;
10804 wd.outdir = outdir;
10805 wd.err = 0;
10806 wd.ctx = ctx;
10807 wd.cleared = 0;
10809 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10810 write_dir_block, &wd);
10811 if (retval)
10812 return retval;
10813 if (wd.err)
10814 return wd.err;
10816 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10817 if (compress)
10818 inode.i_flags &= ~EXT2_INDEX_FL;
10819 else
10820 inode.i_flags |= EXT2_INDEX_FL;
10821 inode.i_size = outdir->num * fs->blocksize;
10822 inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
10823 e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
10825 return 0;
10828 static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
10830 ext2_filsys fs = ctx->fs;
10831 errcode_t retval;
10832 struct ext2_inode inode;
10833 char *dir_buf = NULL;
10834 struct fill_dir_struct fd;
10835 struct out_dir outdir;
10837 outdir.max = outdir.num = 0;
10838 outdir.buf = 0;
10839 outdir.hashes = 0;
10840 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10842 retval = ENOMEM;
10843 fd.harray = 0;
10844 dir_buf = xmalloc(inode.i_size);
10846 fd.max_array = inode.i_size / 32;
10847 fd.num_array = 0;
10848 fd.harray = xmalloc(fd.max_array * sizeof(struct hash_entry));
10850 fd.ctx = ctx;
10851 fd.buf = dir_buf;
10852 fd.inode = &inode;
10853 fd.err = 0;
10854 fd.dir_size = 0;
10855 fd.compress = 0;
10856 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
10857 (inode.i_size / fs->blocksize) < 2)
10858 fd.compress = 1;
10859 fd.parent = 0;
10861 /* Read in the entire directory into memory */
10862 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10863 fill_dir_block, &fd);
10864 if (fd.err) {
10865 retval = fd.err;
10866 goto errout;
10869 /* Sort the list */
10870 resort:
10871 if (fd.compress)
10872 qsort(fd.harray+2, fd.num_array-2,
10873 sizeof(struct hash_entry), name_cmp);
10874 else
10875 qsort(fd.harray, fd.num_array,
10876 sizeof(struct hash_entry), hash_cmp);
10879 * Look for duplicates
10881 if (duplicate_search_and_fix(ctx, fs, ino, &fd))
10882 goto resort;
10884 if (ctx->options & E2F_OPT_NO) {
10885 retval = 0;
10886 goto errout;
10890 * Copy the directory entries. In a htree directory these
10891 * will become the leaf nodes.
10893 retval = copy_dir_entries(fs, &fd, &outdir);
10894 if (retval)
10895 goto errout;
10897 free(dir_buf); dir_buf = 0;
10899 if (!fd.compress) {
10900 /* Calculate the interior nodes */
10901 retval = calculate_tree(fs, &outdir, ino, fd.parent);
10902 if (retval)
10903 goto errout;
10906 retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
10908 errout:
10909 free(dir_buf);
10910 free(fd.harray);
10912 free_out_dir(&outdir);
10913 return retval;
10916 void e2fsck_rehash_directories(e2fsck_t ctx)
10918 struct problem_context pctx;
10919 struct dir_info *dir;
10920 ext2_u32_iterate iter;
10921 ext2_ino_t ino;
10922 errcode_t retval;
10923 int i, cur, max, all_dirs, dir_index, first = 1;
10925 all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
10927 if (!ctx->dirs_to_hash && !all_dirs)
10928 return;
10930 e2fsck_get_lost_and_found(ctx, 0);
10932 clear_problem_context(&pctx);
10934 dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
10935 cur = 0;
10936 if (all_dirs) {
10937 i = 0;
10938 max = e2fsck_get_num_dirinfo(ctx);
10939 } else {
10940 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
10941 &iter);
10942 if (retval) {
10943 pctx.errcode = retval;
10944 fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
10945 return;
10947 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
10949 while (1) {
10950 if (all_dirs) {
10951 if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
10952 break;
10953 ino = dir->ino;
10954 } else {
10955 if (!ext2fs_u32_list_iterate(iter, &ino))
10956 break;
10958 if (ino == ctx->lost_and_found)
10959 continue;
10960 pctx.dir = ino;
10961 if (first) {
10962 fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
10963 first = 0;
10965 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
10966 if (pctx.errcode) {
10967 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10968 fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
10970 if (ctx->progress && !ctx->progress_fd)
10971 e2fsck_simple_progress(ctx, "Rebuilding directory",
10972 100.0 * (float) (++cur) / (float) max, ino);
10974 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10975 if (!all_dirs)
10976 ext2fs_u32_list_iterate_end(iter);
10978 ext2fs_u32_list_free(ctx->dirs_to_hash);
10979 ctx->dirs_to_hash = 0;
10983 * linux/fs/revoke.c
10985 * Journal revoke routines for the generic filesystem journaling code;
10986 * part of the ext2fs journaling system.
10988 * Revoke is the mechanism used to prevent old log records for deleted
10989 * metadata from being replayed on top of newer data using the same
10990 * blocks. The revoke mechanism is used in two separate places:
10992 * + Commit: during commit we write the entire list of the current
10993 * transaction's revoked blocks to the journal
10995 * + Recovery: during recovery we record the transaction ID of all
10996 * revoked blocks. If there are multiple revoke records in the log
10997 * for a single block, only the last one counts, and if there is a log
10998 * entry for a block beyond the last revoke, then that log entry still
10999 * gets replayed.
11001 * We can get interactions between revokes and new log data within a
11002 * single transaction:
11004 * Block is revoked and then journaled:
11005 * The desired end result is the journaling of the new block, so we
11006 * cancel the revoke before the transaction commits.
11008 * Block is journaled and then revoked:
11009 * The revoke must take precedence over the write of the block, so we
11010 * need either to cancel the journal entry or to write the revoke
11011 * later in the log than the log block. In this case, we choose the
11012 * latter: journaling a block cancels any revoke record for that block
11013 * in the current transaction, so any revoke for that block in the
11014 * transaction must have happened after the block was journaled and so
11015 * the revoke must take precedence.
11017 * Block is revoked and then written as data:
11018 * The data write is allowed to succeed, but the revoke is _not_
11019 * cancelled. We still need to prevent old log records from
11020 * overwriting the new data. We don't even need to clear the revoke
11021 * bit here.
11023 * Revoke information on buffers is a tri-state value:
11025 * RevokeValid clear: no cached revoke status, need to look it up
11026 * RevokeValid set, Revoked clear:
11027 * buffer has not been revoked, and cancel_revoke
11028 * need do nothing.
11029 * RevokeValid set, Revoked set:
11030 * buffer has been revoked.
11033 static kmem_cache_t *revoke_record_cache;
11034 static kmem_cache_t *revoke_table_cache;
11036 /* Each revoke record represents one single revoked block. During
11037 journal replay, this involves recording the transaction ID of the
11038 last transaction to revoke this block. */
11040 struct jbd_revoke_record_s
11042 struct list_head hash;
11043 tid_t sequence; /* Used for recovery only */
11044 unsigned long blocknr;
11048 /* The revoke table is just a simple hash table of revoke records. */
11049 struct jbd_revoke_table_s
11051 /* It is conceivable that we might want a larger hash table
11052 * for recovery. Must be a power of two. */
11053 int hash_size;
11054 int hash_shift;
11055 struct list_head *hash_table;
11059 /* Utility functions to maintain the revoke table */
11061 /* Borrowed from buffer.c: this is a tried and tested block hash function */
11062 static int hash(journal_t *journal, unsigned long block)
11064 struct jbd_revoke_table_s *table = journal->j_revoke;
11065 int hash_shift = table->hash_shift;
11067 return ((block << (hash_shift - 6)) ^
11068 (block >> 13) ^
11069 (block << (hash_shift - 12))) & (table->hash_size - 1);
11072 static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
11073 tid_t seq)
11075 struct list_head *hash_list;
11076 struct jbd_revoke_record_s *record;
11078 record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
11079 if (!record)
11080 goto oom;
11082 record->sequence = seq;
11083 record->blocknr = blocknr;
11084 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11085 list_add(&record->hash, hash_list);
11086 return 0;
11088 oom:
11089 return -ENOMEM;
11092 /* Find a revoke record in the journal's hash table. */
11094 static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
11095 unsigned long blocknr)
11097 struct list_head *hash_list;
11098 struct jbd_revoke_record_s *record;
11100 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11102 record = (struct jbd_revoke_record_s *) hash_list->next;
11103 while (&(record->hash) != hash_list) {
11104 if (record->blocknr == blocknr)
11105 return record;
11106 record = (struct jbd_revoke_record_s *) record->hash.next;
11108 return NULL;
11111 int journal_init_revoke_caches(void)
11113 revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
11114 if (revoke_record_cache == 0)
11115 return -ENOMEM;
11117 revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
11118 if (revoke_table_cache == 0) {
11119 do_cache_destroy(revoke_record_cache);
11120 revoke_record_cache = NULL;
11121 return -ENOMEM;
11123 return 0;
11126 void journal_destroy_revoke_caches(void)
11128 do_cache_destroy(revoke_record_cache);
11129 revoke_record_cache = 0;
11130 do_cache_destroy(revoke_table_cache);
11131 revoke_table_cache = 0;
11134 /* Initialise the revoke table for a given journal to a given size. */
11136 int journal_init_revoke(journal_t *journal, int hash_size)
11138 int shift, tmp;
11140 journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
11141 if (!journal->j_revoke)
11142 return -ENOMEM;
11144 /* Check that the hash_size is a power of two */
11145 journal->j_revoke->hash_size = hash_size;
11147 shift = 0;
11148 tmp = hash_size;
11149 while ((tmp >>= 1UL) != 0UL)
11150 shift++;
11151 journal->j_revoke->hash_shift = shift;
11153 journal->j_revoke->hash_table = xmalloc(hash_size * sizeof(struct list_head));
11155 for (tmp = 0; tmp < hash_size; tmp++)
11156 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
11158 return 0;
11161 /* Destoy a journal's revoke table. The table must already be empty! */
11163 void journal_destroy_revoke(journal_t *journal)
11165 struct jbd_revoke_table_s *table;
11166 struct list_head *hash_list;
11167 int i;
11169 table = journal->j_revoke;
11170 if (!table)
11171 return;
11173 for (i=0; i<table->hash_size; i++) {
11174 hash_list = &table->hash_table[i];
11177 free(table->hash_table);
11178 free(table);
11179 journal->j_revoke = NULL;
11183 * Revoke support for recovery.
11185 * Recovery needs to be able to:
11187 * record all revoke records, including the tid of the latest instance
11188 * of each revoke in the journal
11190 * check whether a given block in a given transaction should be replayed
11191 * (ie. has not been revoked by a revoke record in that or a subsequent
11192 * transaction)
11194 * empty the revoke table after recovery.
11198 * First, setting revoke records. We create a new revoke record for
11199 * every block ever revoked in the log as we scan it for recovery, and
11200 * we update the existing records if we find multiple revokes for a
11201 * single block.
11204 int journal_set_revoke(journal_t *journal, unsigned long blocknr,
11205 tid_t sequence)
11207 struct jbd_revoke_record_s *record;
11209 record = find_revoke_record(journal, blocknr);
11210 if (record) {
11211 /* If we have multiple occurences, only record the
11212 * latest sequence number in the hashed record */
11213 if (tid_gt(sequence, record->sequence))
11214 record->sequence = sequence;
11215 return 0;
11217 return insert_revoke_hash(journal, blocknr, sequence);
11221 * Test revoke records. For a given block referenced in the log, has
11222 * that block been revoked? A revoke record with a given transaction
11223 * sequence number revokes all blocks in that transaction and earlier
11224 * ones, but later transactions still need replayed.
11227 int journal_test_revoke(journal_t *journal, unsigned long blocknr,
11228 tid_t sequence)
11230 struct jbd_revoke_record_s *record;
11232 record = find_revoke_record(journal, blocknr);
11233 if (!record)
11234 return 0;
11235 if (tid_gt(sequence, record->sequence))
11236 return 0;
11237 return 1;
11241 * Finally, once recovery is over, we need to clear the revoke table so
11242 * that it can be reused by the running filesystem.
11245 void journal_clear_revoke(journal_t *journal)
11247 int i;
11248 struct list_head *hash_list;
11249 struct jbd_revoke_record_s *record;
11250 struct jbd_revoke_table_s *revoke_var;
11252 revoke_var = journal->j_revoke;
11254 for (i = 0; i < revoke_var->hash_size; i++) {
11255 hash_list = &revoke_var->hash_table[i];
11256 while (!list_empty(hash_list)) {
11257 record = (struct jbd_revoke_record_s*) hash_list->next;
11258 list_del(&record->hash);
11259 free(record);
11265 * e2fsck.c - superblock checks
11268 #define MIN_CHECK 1
11269 #define MAX_CHECK 2
11271 static void check_super_value(e2fsck_t ctx, const char *descr,
11272 unsigned long value, int flags,
11273 unsigned long min_val, unsigned long max_val)
11275 struct problem_context pctx;
11277 if (((flags & MIN_CHECK) && (value < min_val)) ||
11278 ((flags & MAX_CHECK) && (value > max_val))) {
11279 clear_problem_context(&pctx);
11280 pctx.num = value;
11281 pctx.str = descr;
11282 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11283 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11288 * This routine may get stubbed out in special compilations of the
11289 * e2fsck code..
11291 #ifndef EXT2_SPECIAL_DEVICE_SIZE
11292 static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
11294 return (ext2fs_get_device_size(ctx->filesystem_name,
11295 EXT2_BLOCK_SIZE(ctx->fs->super),
11296 &ctx->num_blocks));
11298 #endif
11301 * helper function to release an inode
11303 struct process_block_struct {
11304 e2fsck_t ctx;
11305 char *buf;
11306 struct problem_context *pctx;
11307 int truncating;
11308 int truncate_offset;
11309 e2_blkcnt_t truncate_block;
11310 int truncated_blocks;
11311 int abort;
11312 errcode_t errcode;
11315 static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
11316 e2_blkcnt_t blockcnt,
11317 blk_t ref_blk FSCK_ATTR((unused)),
11318 int ref_offset FSCK_ATTR((unused)),
11319 void *priv_data)
11321 struct process_block_struct *pb;
11322 e2fsck_t ctx;
11323 struct problem_context *pctx;
11324 blk_t blk = *block_nr;
11325 int retval = 0;
11327 pb = (struct process_block_struct *) priv_data;
11328 ctx = pb->ctx;
11329 pctx = pb->pctx;
11331 pctx->blk = blk;
11332 pctx->blkcount = blockcnt;
11334 if (HOLE_BLKADDR(blk))
11335 return 0;
11337 if ((blk < fs->super->s_first_data_block) ||
11338 (blk >= fs->super->s_blocks_count)) {
11339 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
11340 return_abort:
11341 pb->abort = 1;
11342 return BLOCK_ABORT;
11345 if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
11346 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
11347 goto return_abort;
11351 * If we are deleting an orphan, then we leave the fields alone.
11352 * If we are truncating an orphan, then update the inode fields
11353 * and clean up any partial block data.
11355 if (pb->truncating) {
11357 * We only remove indirect blocks if they are
11358 * completely empty.
11360 if (blockcnt < 0) {
11361 int i, limit;
11362 blk_t *bp;
11364 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11365 pb->buf);
11366 if (pb->errcode)
11367 goto return_abort;
11369 limit = fs->blocksize >> 2;
11370 for (i = 0, bp = (blk_t *) pb->buf;
11371 i < limit; i++, bp++)
11372 if (*bp)
11373 return 0;
11376 * We don't remove direct blocks until we've reached
11377 * the truncation block.
11379 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
11380 return 0;
11382 * If part of the last block needs truncating, we do
11383 * it here.
11385 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
11386 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11387 pb->buf);
11388 if (pb->errcode)
11389 goto return_abort;
11390 memset(pb->buf + pb->truncate_offset, 0,
11391 fs->blocksize - pb->truncate_offset);
11392 pb->errcode = io_channel_write_blk(fs->io, blk, 1,
11393 pb->buf);
11394 if (pb->errcode)
11395 goto return_abort;
11397 pb->truncated_blocks++;
11398 *block_nr = 0;
11399 retval |= BLOCK_CHANGED;
11402 ext2fs_block_alloc_stats(fs, blk, -1);
11403 return retval;
11407 * This function releases an inode. Returns 1 if an inconsistency was
11408 * found. If the inode has a link count, then it is being truncated and
11409 * not deleted.
11411 static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
11412 struct ext2_inode *inode, char *block_buf,
11413 struct problem_context *pctx)
11415 struct process_block_struct pb;
11416 ext2_filsys fs = ctx->fs;
11417 errcode_t retval;
11418 __u32 count;
11420 if (!ext2fs_inode_has_valid_blocks(inode))
11421 return 0;
11423 pb.buf = block_buf + 3 * ctx->fs->blocksize;
11424 pb.ctx = ctx;
11425 pb.abort = 0;
11426 pb.errcode = 0;
11427 pb.pctx = pctx;
11428 if (inode->i_links_count) {
11429 pb.truncating = 1;
11430 pb.truncate_block = (e2_blkcnt_t)
11431 ((((long long)inode->i_size_high << 32) +
11432 inode->i_size + fs->blocksize - 1) /
11433 fs->blocksize);
11434 pb.truncate_offset = inode->i_size % fs->blocksize;
11435 } else {
11436 pb.truncating = 0;
11437 pb.truncate_block = 0;
11438 pb.truncate_offset = 0;
11440 pb.truncated_blocks = 0;
11441 retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
11442 block_buf, release_inode_block, &pb);
11443 if (retval) {
11444 bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
11445 ino);
11446 return 1;
11448 if (pb.abort)
11449 return 1;
11451 /* Refresh the inode since ext2fs_block_iterate may have changed it */
11452 e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
11454 if (pb.truncated_blocks)
11455 inode->i_blocks -= pb.truncated_blocks *
11456 (fs->blocksize / 512);
11458 if (inode->i_file_acl) {
11459 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
11460 block_buf, -1, &count);
11461 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
11462 retval = 0;
11463 count = 1;
11465 if (retval) {
11466 bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
11467 ino);
11468 return 1;
11470 if (count == 0)
11471 ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
11472 inode->i_file_acl = 0;
11474 return 0;
11478 * This function releases all of the orphan inodes. It returns 1 if
11479 * it hit some error, and 0 on success.
11481 static int release_orphan_inodes(e2fsck_t ctx)
11483 ext2_filsys fs = ctx->fs;
11484 ext2_ino_t ino, next_ino;
11485 struct ext2_inode inode;
11486 struct problem_context pctx;
11487 char *block_buf;
11489 if ((ino = fs->super->s_last_orphan) == 0)
11490 return 0;
11493 * Win or lose, we won't be using the head of the orphan inode
11494 * list again.
11496 fs->super->s_last_orphan = 0;
11497 ext2fs_mark_super_dirty(fs);
11500 * If the filesystem contains errors, don't run the orphan
11501 * list, since the orphan list can't be trusted; and we're
11502 * going to be running a full e2fsck run anyway...
11504 if (fs->super->s_state & EXT2_ERROR_FS)
11505 return 0;
11507 if ((ino < EXT2_FIRST_INODE(fs->super)) ||
11508 (ino > fs->super->s_inodes_count)) {
11509 clear_problem_context(&pctx);
11510 pctx.ino = ino;
11511 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
11512 return 1;
11515 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
11516 "block iterate buffer");
11517 e2fsck_read_bitmaps(ctx);
11519 while (ino) {
11520 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
11521 clear_problem_context(&pctx);
11522 pctx.ino = ino;
11523 pctx.inode = &inode;
11524 pctx.str = inode.i_links_count ? _("Truncating") :
11525 _("Clearing");
11527 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
11529 next_ino = inode.i_dtime;
11530 if (next_ino &&
11531 ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
11532 (next_ino > fs->super->s_inodes_count))) {
11533 pctx.ino = next_ino;
11534 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
11535 goto return_abort;
11538 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
11539 goto return_abort;
11541 if (!inode.i_links_count) {
11542 ext2fs_inode_alloc_stats2(fs, ino, -1,
11543 LINUX_S_ISDIR(inode.i_mode));
11544 inode.i_dtime = time(NULL);
11545 } else {
11546 inode.i_dtime = 0;
11548 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
11549 ino = next_ino;
11551 ext2fs_free_mem(&block_buf);
11552 return 0;
11553 return_abort:
11554 ext2fs_free_mem(&block_buf);
11555 return 1;
11559 * Check the resize inode to make sure it is sane. We check both for
11560 * the case where on-line resizing is not enabled (in which case the
11561 * resize inode should be cleared) as well as the case where on-line
11562 * resizing is enabled.
11564 static void check_resize_inode(e2fsck_t ctx)
11566 ext2_filsys fs = ctx->fs;
11567 struct ext2_inode inode;
11568 struct problem_context pctx;
11569 int i, j, gdt_off, ind_off;
11570 blk_t blk, pblk, expect;
11571 __u32 *dind_buf = NULL, *ind_buf;
11572 errcode_t retval;
11574 clear_problem_context(&pctx);
11577 * If the resize inode feature isn't set, then
11578 * s_reserved_gdt_blocks must be zero.
11580 if (!(fs->super->s_feature_compat &
11581 EXT2_FEATURE_COMPAT_RESIZE_INO)) {
11582 if (fs->super->s_reserved_gdt_blocks) {
11583 pctx.num = fs->super->s_reserved_gdt_blocks;
11584 if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
11585 &pctx)) {
11586 fs->super->s_reserved_gdt_blocks = 0;
11587 ext2fs_mark_super_dirty(fs);
11592 /* Read the resize inode */
11593 pctx.ino = EXT2_RESIZE_INO;
11594 retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
11595 if (retval) {
11596 if (fs->super->s_feature_compat &
11597 EXT2_FEATURE_COMPAT_RESIZE_INO)
11598 ctx->flags |= E2F_FLAG_RESIZE_INODE;
11599 return;
11603 * If the resize inode feature isn't set, check to make sure
11604 * the resize inode is cleared; then we're done.
11606 if (!(fs->super->s_feature_compat &
11607 EXT2_FEATURE_COMPAT_RESIZE_INO)) {
11608 for (i=0; i < EXT2_N_BLOCKS; i++) {
11609 if (inode.i_block[i])
11610 break;
11612 if ((i < EXT2_N_BLOCKS) &&
11613 fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
11614 memset(&inode, 0, sizeof(inode));
11615 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11616 "clear_resize");
11618 return;
11622 * The resize inode feature is enabled; check to make sure the
11623 * only block in use is the double indirect block
11625 blk = inode.i_block[EXT2_DIND_BLOCK];
11626 for (i=0; i < EXT2_N_BLOCKS; i++) {
11627 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
11628 break;
11630 if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
11631 !(inode.i_mode & LINUX_S_IFREG) ||
11632 (blk < fs->super->s_first_data_block ||
11633 blk >= fs->super->s_blocks_count)) {
11634 resize_inode_invalid:
11635 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
11636 memset(&inode, 0, sizeof(inode));
11637 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11638 "clear_resize");
11639 ctx->flags |= E2F_FLAG_RESIZE_INODE;
11641 if (!(ctx->options & E2F_OPT_READONLY)) {
11642 fs->super->s_state &= ~EXT2_VALID_FS;
11643 ext2fs_mark_super_dirty(fs);
11645 goto cleanup;
11647 dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
11648 "resize dind buffer");
11649 ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
11651 retval = ext2fs_read_ind_block(fs, blk, dind_buf);
11652 if (retval)
11653 goto resize_inode_invalid;
11655 gdt_off = fs->desc_blocks;
11656 pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
11657 for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
11658 i++, gdt_off++, pblk++) {
11659 gdt_off %= fs->blocksize/4;
11660 if (dind_buf[gdt_off] != pblk)
11661 goto resize_inode_invalid;
11662 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
11663 if (retval)
11664 goto resize_inode_invalid;
11665 ind_off = 0;
11666 for (j = 1; j < fs->group_desc_count; j++) {
11667 if (!ext2fs_bg_has_super(fs, j))
11668 continue;
11669 expect = pblk + (j * fs->super->s_blocks_per_group);
11670 if (ind_buf[ind_off] != expect)
11671 goto resize_inode_invalid;
11672 ind_off++;
11676 cleanup:
11677 ext2fs_free_mem(&dind_buf);
11680 static void check_super_block(e2fsck_t ctx)
11682 ext2_filsys fs = ctx->fs;
11683 blk_t first_block, last_block;
11684 struct ext2_super_block *sb = fs->super;
11685 struct ext2_group_desc *gd;
11686 blk_t blocks_per_group = fs->super->s_blocks_per_group;
11687 blk_t bpg_max;
11688 int inodes_per_block;
11689 int ipg_max;
11690 int inode_size;
11691 dgrp_t i;
11692 blk_t should_be;
11693 struct problem_context pctx;
11694 __u32 free_blocks = 0, free_inodes = 0;
11696 inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
11697 ipg_max = inodes_per_block * (blocks_per_group - 4);
11698 if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
11699 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
11700 bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
11701 if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
11702 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
11704 ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11705 sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
11706 ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11707 sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
11708 ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
11709 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
11711 clear_problem_context(&pctx);
11714 * Verify the super block constants...
11716 check_super_value(ctx, "inodes_count", sb->s_inodes_count,
11717 MIN_CHECK, 1, 0);
11718 check_super_value(ctx, "blocks_count", sb->s_blocks_count,
11719 MIN_CHECK, 1, 0);
11720 check_super_value(ctx, "first_data_block", sb->s_first_data_block,
11721 MAX_CHECK, 0, sb->s_blocks_count);
11722 check_super_value(ctx, "log_block_size", sb->s_log_block_size,
11723 MIN_CHECK | MAX_CHECK, 0,
11724 EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
11725 check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
11726 MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
11727 check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
11728 MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
11729 bpg_max);
11730 check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
11731 MIN_CHECK | MAX_CHECK, 8, bpg_max);
11732 check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
11733 MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
11734 check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
11735 MAX_CHECK, 0, sb->s_blocks_count / 2);
11736 check_super_value(ctx, "reserved_gdt_blocks",
11737 sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
11738 fs->blocksize/4);
11739 inode_size = EXT2_INODE_SIZE(sb);
11740 check_super_value(ctx, "inode_size",
11741 inode_size, MIN_CHECK | MAX_CHECK,
11742 EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
11743 if (inode_size & (inode_size - 1)) {
11744 pctx.num = inode_size;
11745 pctx.str = "inode_size";
11746 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11747 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11748 return;
11751 if (!ctx->num_blocks) {
11752 pctx.errcode = e2fsck_get_device_size(ctx);
11753 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
11754 fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
11755 ctx->flags |= E2F_FLAG_ABORT;
11756 return;
11758 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
11759 (ctx->num_blocks < sb->s_blocks_count)) {
11760 pctx.blk = sb->s_blocks_count;
11761 pctx.blk2 = ctx->num_blocks;
11762 if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
11763 ctx->flags |= E2F_FLAG_ABORT;
11764 return;
11769 if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
11770 pctx.blk = EXT2_BLOCK_SIZE(sb);
11771 pctx.blk2 = EXT2_FRAG_SIZE(sb);
11772 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
11773 ctx->flags |= E2F_FLAG_ABORT;
11774 return;
11777 should_be = sb->s_frags_per_group >>
11778 (sb->s_log_block_size - sb->s_log_frag_size);
11779 if (sb->s_blocks_per_group != should_be) {
11780 pctx.blk = sb->s_blocks_per_group;
11781 pctx.blk2 = should_be;
11782 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
11783 ctx->flags |= E2F_FLAG_ABORT;
11784 return;
11787 should_be = (sb->s_log_block_size == 0) ? 1 : 0;
11788 if (sb->s_first_data_block != should_be) {
11789 pctx.blk = sb->s_first_data_block;
11790 pctx.blk2 = should_be;
11791 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
11792 ctx->flags |= E2F_FLAG_ABORT;
11793 return;
11796 should_be = sb->s_inodes_per_group * fs->group_desc_count;
11797 if (sb->s_inodes_count != should_be) {
11798 pctx.ino = sb->s_inodes_count;
11799 pctx.ino2 = should_be;
11800 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
11801 sb->s_inodes_count = should_be;
11802 ext2fs_mark_super_dirty(fs);
11807 * Verify the group descriptors....
11809 first_block = sb->s_first_data_block;
11810 last_block = first_block + blocks_per_group;
11812 for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
11813 pctx.group = i;
11815 if (i == fs->group_desc_count - 1)
11816 last_block = sb->s_blocks_count;
11817 if ((gd->bg_block_bitmap < first_block) ||
11818 (gd->bg_block_bitmap >= last_block)) {
11819 pctx.blk = gd->bg_block_bitmap;
11820 if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
11821 gd->bg_block_bitmap = 0;
11823 if (gd->bg_block_bitmap == 0) {
11824 ctx->invalid_block_bitmap_flag[i]++;
11825 ctx->invalid_bitmaps++;
11827 if ((gd->bg_inode_bitmap < first_block) ||
11828 (gd->bg_inode_bitmap >= last_block)) {
11829 pctx.blk = gd->bg_inode_bitmap;
11830 if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
11831 gd->bg_inode_bitmap = 0;
11833 if (gd->bg_inode_bitmap == 0) {
11834 ctx->invalid_inode_bitmap_flag[i]++;
11835 ctx->invalid_bitmaps++;
11837 if ((gd->bg_inode_table < first_block) ||
11838 ((gd->bg_inode_table +
11839 fs->inode_blocks_per_group - 1) >= last_block)) {
11840 pctx.blk = gd->bg_inode_table;
11841 if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
11842 gd->bg_inode_table = 0;
11844 if (gd->bg_inode_table == 0) {
11845 ctx->invalid_inode_table_flag[i]++;
11846 ctx->invalid_bitmaps++;
11848 free_blocks += gd->bg_free_blocks_count;
11849 free_inodes += gd->bg_free_inodes_count;
11850 first_block += sb->s_blocks_per_group;
11851 last_block += sb->s_blocks_per_group;
11853 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
11854 (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
11855 (gd->bg_used_dirs_count > sb->s_inodes_per_group))
11856 ext2fs_unmark_valid(fs);
11860 * Update the global counts from the block group counts. This
11861 * is needed for an experimental patch which eliminates
11862 * locking the entire filesystem when allocating blocks or
11863 * inodes; if the filesystem is not unmounted cleanly, the
11864 * global counts may not be accurate.
11866 if ((free_blocks != sb->s_free_blocks_count) ||
11867 (free_inodes != sb->s_free_inodes_count)) {
11868 if (ctx->options & E2F_OPT_READONLY)
11869 ext2fs_unmark_valid(fs);
11870 else {
11871 sb->s_free_blocks_count = free_blocks;
11872 sb->s_free_inodes_count = free_inodes;
11873 ext2fs_mark_super_dirty(fs);
11877 if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
11878 (sb->s_free_inodes_count > sb->s_inodes_count))
11879 ext2fs_unmark_valid(fs);
11883 * If we have invalid bitmaps, set the error state of the
11884 * filesystem.
11886 if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
11887 sb->s_state &= ~EXT2_VALID_FS;
11888 ext2fs_mark_super_dirty(fs);
11891 clear_problem_context(&pctx);
11894 * If the UUID field isn't assigned, assign it.
11896 if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
11897 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
11898 generate_uuid(sb->s_uuid);
11899 ext2fs_mark_super_dirty(fs);
11900 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
11904 /* FIXME - HURD support?
11905 * For the Hurd, check to see if the filetype option is set,
11906 * since it doesn't support it.
11908 if (!(ctx->options & E2F_OPT_READONLY) &&
11909 fs->super->s_creator_os == EXT2_OS_HURD &&
11910 (fs->super->s_feature_incompat &
11911 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
11912 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
11913 fs->super->s_feature_incompat &=
11914 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
11915 ext2fs_mark_super_dirty(fs);
11920 * If we have any of the compatibility flags set, we need to have a
11921 * revision 1 filesystem. Most kernels will not check the flags on
11922 * a rev 0 filesystem and we may have corruption issues because of
11923 * the incompatible changes to the filesystem.
11925 if (!(ctx->options & E2F_OPT_READONLY) &&
11926 fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
11927 (fs->super->s_feature_compat ||
11928 fs->super->s_feature_ro_compat ||
11929 fs->super->s_feature_incompat) &&
11930 fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
11931 ext2fs_update_dynamic_rev(fs);
11932 ext2fs_mark_super_dirty(fs);
11935 check_resize_inode(ctx);
11938 * Clean up any orphan inodes, if present.
11940 if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
11941 fs->super->s_state &= ~EXT2_VALID_FS;
11942 ext2fs_mark_super_dirty(fs);
11946 * Move the ext3 journal file, if necessary.
11948 e2fsck_move_ext3_journal(ctx);
11952 * swapfs.c --- byte-swap an ext2 filesystem
11955 #ifdef ENABLE_SWAPFS
11957 struct swap_block_struct {
11958 ext2_ino_t ino;
11959 int isdir;
11960 errcode_t errcode;
11961 char *dir_buf;
11962 struct ext2_inode *inode;
11966 * This is a helper function for block_iterate. We mark all of the
11967 * indirect and direct blocks as changed, so that block_iterate will
11968 * write them out.
11970 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
11971 void *priv_data)
11973 errcode_t retval;
11975 struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
11977 if (sb->isdir && (blockcnt >= 0) && *block_nr) {
11978 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
11979 if (retval) {
11980 sb->errcode = retval;
11981 return BLOCK_ABORT;
11983 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
11984 if (retval) {
11985 sb->errcode = retval;
11986 return BLOCK_ABORT;
11989 if (blockcnt >= 0) {
11990 if (blockcnt < EXT2_NDIR_BLOCKS)
11991 return 0;
11992 return BLOCK_CHANGED;
11994 if (blockcnt == BLOCK_COUNT_IND) {
11995 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
11996 return 0;
11997 return BLOCK_CHANGED;
11999 if (blockcnt == BLOCK_COUNT_DIND) {
12000 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
12001 return 0;
12002 return BLOCK_CHANGED;
12004 if (blockcnt == BLOCK_COUNT_TIND) {
12005 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
12006 return 0;
12007 return BLOCK_CHANGED;
12009 return BLOCK_CHANGED;
12013 * This function is responsible for byte-swapping all of the indirect,
12014 * block pointers. It is also responsible for byte-swapping directories.
12016 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
12017 struct ext2_inode *inode)
12019 errcode_t retval;
12020 struct swap_block_struct sb;
12022 sb.ino = ino;
12023 sb.inode = inode;
12024 sb.dir_buf = block_buf + ctx->fs->blocksize*3;
12025 sb.errcode = 0;
12026 sb.isdir = 0;
12027 if (LINUX_S_ISDIR(inode->i_mode))
12028 sb.isdir = 1;
12030 retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
12031 swap_block, &sb);
12032 if (retval) {
12033 bb_error_msg(_("while calling ext2fs_block_iterate"));
12034 ctx->flags |= E2F_FLAG_ABORT;
12035 return;
12037 if (sb.errcode) {
12038 bb_error_msg(_("while calling iterator function"));
12039 ctx->flags |= E2F_FLAG_ABORT;
12040 return;
12044 static void swap_inodes(e2fsck_t ctx)
12046 ext2_filsys fs = ctx->fs;
12047 dgrp_t group;
12048 unsigned int i;
12049 ext2_ino_t ino = 1;
12050 char *buf, *block_buf;
12051 errcode_t retval;
12052 struct ext2_inode * inode;
12054 e2fsck_use_inode_shortcuts(ctx, 1);
12056 retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
12057 &buf);
12058 if (retval) {
12059 bb_error_msg(_("while allocating inode buffer"));
12060 ctx->flags |= E2F_FLAG_ABORT;
12061 return;
12063 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12064 "block interate buffer");
12065 for (group = 0; group < fs->group_desc_count; group++) {
12066 retval = io_channel_read_blk(fs->io,
12067 fs->group_desc[group].bg_inode_table,
12068 fs->inode_blocks_per_group, buf);
12069 if (retval) {
12070 bb_error_msg(_("while reading inode table (group %d)"),
12071 group);
12072 ctx->flags |= E2F_FLAG_ABORT;
12073 return;
12075 inode = (struct ext2_inode *) buf;
12076 for (i=0; i < fs->super->s_inodes_per_group;
12077 i++, ino++, inode++) {
12078 ctx->stashed_ino = ino;
12079 ctx->stashed_inode = inode;
12081 if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
12082 ext2fs_swap_inode(fs, inode, inode, 0);
12085 * Skip deleted files.
12087 if (inode->i_links_count == 0)
12088 continue;
12090 if (LINUX_S_ISDIR(inode->i_mode) ||
12091 ((inode->i_block[EXT2_IND_BLOCK] ||
12092 inode->i_block[EXT2_DIND_BLOCK] ||
12093 inode->i_block[EXT2_TIND_BLOCK]) &&
12094 ext2fs_inode_has_valid_blocks(inode)))
12095 swap_inode_blocks(ctx, ino, block_buf, inode);
12097 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12098 return;
12100 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12101 ext2fs_swap_inode(fs, inode, inode, 1);
12103 retval = io_channel_write_blk(fs->io,
12104 fs->group_desc[group].bg_inode_table,
12105 fs->inode_blocks_per_group, buf);
12106 if (retval) {
12107 bb_error_msg(_("while writing inode table (group %d)"),
12108 group);
12109 ctx->flags |= E2F_FLAG_ABORT;
12110 return;
12113 ext2fs_free_mem(&buf);
12114 ext2fs_free_mem(&block_buf);
12115 e2fsck_use_inode_shortcuts(ctx, 0);
12116 ext2fs_flush_icache(fs);
12119 #if defined(__powerpc__) && BB_BIG_ENDIAN
12121 * On the PowerPC, the big-endian variant of the ext2 filesystem
12122 * has its bitmaps stored as 32-bit words with bit 0 as the LSB
12123 * of each word. Thus a bitmap with only bit 0 set would be, as
12124 * a string of bytes, 00 00 00 01 00 ...
12125 * To cope with this, we byte-reverse each word of a bitmap if
12126 * we have a big-endian filesystem, that is, if we are *not*
12127 * byte-swapping other word-sized numbers.
12129 #define EXT2_BIG_ENDIAN_BITMAPS
12130 #endif
12132 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12133 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
12135 __u32 *p = (__u32 *) bmap->bitmap;
12136 int n, nbytes = (bmap->end - bmap->start + 7) / 8;
12138 for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
12139 *p = ext2fs_swab32(*p);
12141 #endif
12144 #ifdef ENABLE_SWAPFS
12145 static void swap_filesys(e2fsck_t ctx)
12147 ext2_filsys fs = ctx->fs;
12148 if (!(ctx->options & E2F_OPT_PREEN))
12149 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
12151 /* Byte swap */
12153 if (fs->super->s_mnt_count) {
12154 fprintf(stderr, _("%s: the filesystem must be freshly "
12155 "checked using fsck\n"
12156 "and not mounted before trying to "
12157 "byte-swap it.\n"), ctx->device_name);
12158 ctx->flags |= E2F_FLAG_ABORT;
12159 return;
12161 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
12162 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
12163 EXT2_FLAG_SWAP_BYTES_WRITE);
12164 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
12165 } else {
12166 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
12167 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
12169 swap_inodes(ctx);
12170 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12171 return;
12172 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12173 fs->flags |= EXT2_FLAG_SWAP_BYTES;
12174 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
12175 EXT2_FLAG_SWAP_BYTES_WRITE);
12177 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12178 e2fsck_read_bitmaps(ctx);
12179 ext2fs_swap_bitmap(fs->inode_map);
12180 ext2fs_swap_bitmap(fs->block_map);
12181 fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
12182 #endif
12183 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
12184 ext2fs_flush(fs);
12185 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
12187 #endif /* ENABLE_SWAPFS */
12189 #endif
12192 * util.c --- miscellaneous utilities
12196 void *e2fsck_allocate_memory(e2fsck_t ctx EXT2FS_ATTR((unused)), unsigned int size,
12197 const char *description EXT2FS_ATTR((unused)))
12199 void *ret;
12201 ret = xzalloc(size);
12202 return ret;
12205 static char *string_copy(const char *str, int len)
12207 char *ret;
12209 if (!str)
12210 return NULL;
12211 if (!len)
12212 len = strlen(str);
12213 ret = xmalloc(len+1);
12214 strncpy(ret, str, len);
12215 ret[len] = 0;
12216 return ret;
12219 #ifndef HAVE_CONIO_H
12220 static int read_a_char(void)
12222 char c;
12223 int r;
12224 int fail = 0;
12226 while (1) {
12227 if (e2fsck_global_ctx &&
12228 (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
12229 return 3;
12231 r = read(0, &c, 1);
12232 if (r == 1)
12233 return c;
12234 if (fail++ > 100)
12235 break;
12237 return EOF;
12239 #endif
12241 static int ask_yn(const char * string, int def)
12243 int c;
12244 const char *defstr;
12245 static const char short_yes[] = "yY";
12246 static const char short_no[] = "nN";
12248 #ifdef HAVE_TERMIOS_H
12249 struct termios termios, tmp;
12251 tcgetattr (0, &termios);
12252 tmp = termios;
12253 tmp.c_lflag &= ~(ICANON | ECHO);
12254 tmp.c_cc[VMIN] = 1;
12255 tmp.c_cc[VTIME] = 0;
12256 tcsetattr_stdin_TCSANOW(&tmp);
12257 #endif
12259 if (def == 1)
12260 defstr = "<y>";
12261 else if (def == 0)
12262 defstr = "<n>";
12263 else
12264 defstr = " (y/n)";
12265 printf("%s%s? ", string, defstr);
12266 while (1) {
12267 fflush (stdout);
12268 if ((c = read_a_char()) == EOF)
12269 break;
12270 if (c == 3) {
12271 #ifdef HAVE_TERMIOS_H
12272 tcsetattr_stdin_TCSANOW(&termios);
12273 #endif
12274 if (e2fsck_global_ctx &&
12275 e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
12276 puts("\n");
12277 longjmp(e2fsck_global_ctx->abort_loc, 1);
12279 puts(_("cancelled!\n"));
12280 return 0;
12282 if (strchr(short_yes, (char) c)) {
12283 def = 1;
12284 break;
12286 else if (strchr(short_no, (char) c)) {
12287 def = 0;
12288 break;
12290 else if ((c == ' ' || c == '\n') && (def != -1))
12291 break;
12293 if (def)
12294 puts("yes\n");
12295 else
12296 puts ("no\n");
12297 #ifdef HAVE_TERMIOS_H
12298 tcsetattr_stdin_TCSANOW(&termios);
12299 #endif
12300 return def;
12303 int ask (e2fsck_t ctx, const char * string, int def)
12305 if (ctx->options & E2F_OPT_NO) {
12306 printf(_("%s? no\n\n"), string);
12307 return 0;
12309 if (ctx->options & E2F_OPT_YES) {
12310 printf(_("%s? yes\n\n"), string);
12311 return 1;
12313 if (ctx->options & E2F_OPT_PREEN) {
12314 printf("%s? %s\n\n", string, def ? _("yes") : _("no"));
12315 return def;
12317 return ask_yn(string, def);
12320 void e2fsck_read_bitmaps(e2fsck_t ctx)
12322 ext2_filsys fs = ctx->fs;
12323 errcode_t retval;
12325 if (ctx->invalid_bitmaps) {
12326 bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12327 ctx->device_name);
12328 bb_error_msg_and_die(0);
12331 ehandler_operation(_("reading inode and block bitmaps"));
12332 retval = ext2fs_read_bitmaps(fs);
12333 ehandler_operation(0);
12334 if (retval) {
12335 bb_error_msg(_("while retrying to read bitmaps for %s"),
12336 ctx->device_name);
12337 bb_error_msg_and_die(0);
12341 static void e2fsck_write_bitmaps(e2fsck_t ctx)
12343 ext2_filsys fs = ctx->fs;
12344 errcode_t retval;
12346 if (ext2fs_test_bb_dirty(fs)) {
12347 ehandler_operation(_("writing block bitmaps"));
12348 retval = ext2fs_write_block_bitmap(fs);
12349 ehandler_operation(0);
12350 if (retval) {
12351 bb_error_msg(_("while retrying to write block bitmaps for %s"),
12352 ctx->device_name);
12353 bb_error_msg_and_die(0);
12357 if (ext2fs_test_ib_dirty(fs)) {
12358 ehandler_operation(_("writing inode bitmaps"));
12359 retval = ext2fs_write_inode_bitmap(fs);
12360 ehandler_operation(0);
12361 if (retval) {
12362 bb_error_msg(_("while retrying to write inode bitmaps for %s"),
12363 ctx->device_name);
12364 bb_error_msg_and_die(0);
12369 void preenhalt(e2fsck_t ctx)
12371 ext2_filsys fs = ctx->fs;
12373 if (!(ctx->options & E2F_OPT_PREEN))
12374 return;
12375 fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12376 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12377 ctx->device_name);
12378 if (fs != NULL) {
12379 fs->super->s_state |= EXT2_ERROR_FS;
12380 ext2fs_mark_super_dirty(fs);
12381 ext2fs_close(fs);
12383 exit(EXIT_UNCORRECTED);
12386 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12387 struct ext2_inode * inode, const char *proc)
12389 int retval;
12391 retval = ext2fs_read_inode(ctx->fs, ino, inode);
12392 if (retval) {
12393 bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
12394 bb_error_msg_and_die(0);
12398 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12399 struct ext2_inode * inode, int bufsize,
12400 const char *proc)
12402 int retval;
12404 retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12405 if (retval) {
12406 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12407 bb_error_msg_and_die(0);
12411 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12412 struct ext2_inode * inode, const char *proc)
12414 int retval;
12416 retval = ext2fs_write_inode(ctx->fs, ino, inode);
12417 if (retval) {
12418 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12419 bb_error_msg_and_die(0);
12423 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12424 io_manager manager)
12426 struct ext2_super_block *sb;
12427 io_channel io = NULL;
12428 void *buf = NULL;
12429 int blocksize;
12430 blk_t superblock, ret_sb = 8193;
12432 if (fs && fs->super) {
12433 ret_sb = (fs->super->s_blocks_per_group +
12434 fs->super->s_first_data_block);
12435 if (ctx) {
12436 ctx->superblock = ret_sb;
12437 ctx->blocksize = fs->blocksize;
12439 return ret_sb;
12442 if (ctx) {
12443 if (ctx->blocksize) {
12444 ret_sb = ctx->blocksize * 8;
12445 if (ctx->blocksize == 1024)
12446 ret_sb++;
12447 ctx->superblock = ret_sb;
12448 return ret_sb;
12450 ctx->superblock = ret_sb;
12451 ctx->blocksize = 1024;
12454 if (!name || !manager)
12455 goto cleanup;
12457 if (manager->open(name, 0, &io) != 0)
12458 goto cleanup;
12460 if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12461 goto cleanup;
12462 sb = (struct ext2_super_block *) buf;
12464 for (blocksize = EXT2_MIN_BLOCK_SIZE;
12465 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
12466 superblock = blocksize*8;
12467 if (blocksize == 1024)
12468 superblock++;
12469 io_channel_set_blksize(io, blocksize);
12470 if (io_channel_read_blk(io, superblock,
12471 -SUPERBLOCK_SIZE, buf))
12472 continue;
12473 #if BB_BIG_ENDIAN
12474 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12475 ext2fs_swap_super(sb);
12476 #endif
12477 if (sb->s_magic == EXT2_SUPER_MAGIC) {
12478 ret_sb = superblock;
12479 if (ctx) {
12480 ctx->superblock = superblock;
12481 ctx->blocksize = blocksize;
12483 break;
12487 cleanup:
12488 if (io)
12489 io_channel_close(io);
12490 ext2fs_free_mem(&buf);
12491 return ret_sb;
12496 * This function runs through the e2fsck passes and calls them all,
12497 * returning restart, abort, or cancel as necessary...
12499 typedef void (*pass_t)(e2fsck_t ctx);
12501 static const pass_t e2fsck_passes[] = {
12502 e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12503 e2fsck_pass5, 0 };
12505 #define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12507 static int e2fsck_run(e2fsck_t ctx)
12509 int i;
12510 pass_t e2fsck_pass;
12512 if (setjmp(ctx->abort_loc)) {
12513 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12514 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12516 ctx->flags |= E2F_FLAG_SETJMP_OK;
12518 for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12519 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12520 break;
12521 e2fsck_pass(ctx);
12522 if (ctx->progress)
12523 (void) (ctx->progress)(ctx, 0, 0, 0);
12525 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12527 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12528 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12529 return 0;
12534 * unix.c - The unix-specific code for e2fsck
12538 /* Command line options */
12539 static int swapfs;
12540 #ifdef ENABLE_SWAPFS
12541 static int normalize_swapfs;
12542 #endif
12543 static int cflag; /* check disk */
12544 static int show_version_only;
12545 static int verbose;
12547 #define P_E2(singular, plural, n) n, ((n) == 1 ? singular : plural)
12549 static void show_stats(e2fsck_t ctx)
12551 ext2_filsys fs = ctx->fs;
12552 int inodes, inodes_used, blocks, blocks_used;
12553 int dir_links;
12554 int num_files, num_links;
12555 int frag_percent;
12557 dir_links = 2 * ctx->fs_directory_count - 1;
12558 num_files = ctx->fs_total_count - dir_links;
12559 num_links = ctx->fs_links_count - dir_links;
12560 inodes = fs->super->s_inodes_count;
12561 inodes_used = (fs->super->s_inodes_count -
12562 fs->super->s_free_inodes_count);
12563 blocks = fs->super->s_blocks_count;
12564 blocks_used = (fs->super->s_blocks_count -
12565 fs->super->s_free_blocks_count);
12567 frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12568 frag_percent = (frag_percent + 5) / 10;
12570 if (!verbose) {
12571 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12572 ctx->device_name, inodes_used, inodes,
12573 frag_percent / 10, frag_percent % 10,
12574 blocks_used, blocks);
12575 return;
12577 printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12578 100 * inodes_used / inodes);
12579 printf("%8d non-contiguous inode%s (%0d.%d%%)\n",
12580 P_E2("", "s", ctx->fs_fragmented),
12581 frag_percent / 10, frag_percent % 10);
12582 printf(_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12583 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12584 printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12585 (int) ((long long) 100 * blocks_used / blocks));
12586 printf("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12587 printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12588 printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12589 printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12590 printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12591 printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12592 printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12593 printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12594 printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12595 printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12596 printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12599 static void check_mount(e2fsck_t ctx)
12601 errcode_t retval;
12602 int cont;
12604 retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12605 &ctx->mount_flags);
12606 if (retval) {
12607 bb_error_msg(_("while determining whether %s is mounted"),
12608 ctx->filesystem_name);
12609 return;
12613 * If the filesystem isn't mounted, or it's the root filesystem
12614 * and it's mounted read-only, then everything's fine.
12616 if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12617 ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12618 (ctx->mount_flags & EXT2_MF_READONLY)))
12619 return;
12621 if (ctx->options & E2F_OPT_READONLY) {
12622 printf(_("Warning! %s is mounted.\n"), ctx->filesystem_name);
12623 return;
12626 printf(_("%s is mounted. "), ctx->filesystem_name);
12627 if (!ctx->interactive)
12628 bb_error_msg_and_die(_("can't continue, aborting"));
12629 printf(_("\n\n\007\007\007\007WARNING!!! "
12630 "Running e2fsck on a mounted filesystem may cause\n"
12631 "SEVERE filesystem damage.\007\007\007\n\n"));
12632 cont = ask_yn(_("Do you really want to continue"), -1);
12633 if (!cont) {
12634 printf(_("check aborted.\n"));
12635 exit(0);
12639 static int is_on_batt(void)
12641 FILE *f;
12642 DIR *d;
12643 char tmp[80], tmp2[80], fname[80];
12644 unsigned int acflag;
12645 struct dirent* de;
12647 f = fopen_for_read("/proc/apm");
12648 if (f) {
12649 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12650 acflag = 1;
12651 fclose(f);
12652 return (acflag != 1);
12654 d = opendir("/proc/acpi/ac_adapter");
12655 if (d) {
12656 while ((de=readdir(d)) != NULL) {
12657 if (!strncmp(".", de->d_name, 1))
12658 continue;
12659 snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12660 de->d_name);
12661 f = fopen_for_read(fname);
12662 if (!f)
12663 continue;
12664 if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12665 tmp[0] = 0;
12666 fclose(f);
12667 if (strncmp(tmp, "off-line", 8) == 0) {
12668 closedir(d);
12669 return 1;
12672 closedir(d);
12674 return 0;
12678 * This routine checks to see if a filesystem can be skipped; if so,
12679 * it will exit with EXIT_OK. Under some conditions it will print a
12680 * message explaining why a check is being forced.
12682 static void check_if_skip(e2fsck_t ctx)
12684 ext2_filsys fs = ctx->fs;
12685 const char *reason = NULL;
12686 unsigned int reason_arg = 0;
12687 long next_check;
12688 int batt = is_on_batt();
12689 time_t now = time(NULL);
12691 if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12692 return;
12694 if ((fs->super->s_state & EXT2_ERROR_FS) ||
12695 !ext2fs_test_valid(fs))
12696 reason = _(" contains a file system with errors");
12697 else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12698 reason = _(" was not cleanly unmounted");
12699 else if ((fs->super->s_max_mnt_count > 0) &&
12700 (fs->super->s_mnt_count >=
12701 (unsigned) fs->super->s_max_mnt_count)) {
12702 reason = _(" has been mounted %u times without being checked");
12703 reason_arg = fs->super->s_mnt_count;
12704 if (batt && (fs->super->s_mnt_count <
12705 (unsigned) fs->super->s_max_mnt_count*2))
12706 reason = 0;
12707 } else if (!(ctx->options & E2F_OPT_PREEN) &&
12708 fs->super->s_checkinterval &&
12709 ((now - fs->super->s_lastcheck) >=
12710 fs->super->s_checkinterval)) {
12711 reason = _(" has gone %u days without being checked");
12712 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12713 if (batt && ((now - fs->super->s_lastcheck) <
12714 fs->super->s_checkinterval*2))
12715 reason = 0;
12717 if (reason) {
12718 fputs(ctx->device_name, stdout);
12719 printf(reason, reason_arg);
12720 fputs(_(", check forced.\n"), stdout);
12721 return;
12723 printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12724 fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12725 fs->super->s_inodes_count,
12726 fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12727 fs->super->s_blocks_count);
12728 next_check = 100000;
12729 if (fs->super->s_max_mnt_count > 0) {
12730 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12731 if (next_check <= 0)
12732 next_check = 1;
12734 if (fs->super->s_checkinterval &&
12735 ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12736 next_check = 1;
12737 if (next_check <= 5) {
12738 if (next_check == 1)
12739 fputs(_(" (check after next mount)"), stdout);
12740 else
12741 printf(_(" (check in %ld mounts)"), next_check);
12743 bb_putchar('\n');
12744 ext2fs_close(fs);
12745 ctx->fs = NULL;
12746 e2fsck_free_context(ctx);
12747 exit(EXIT_OK);
12751 * For completion notice
12753 struct percent_tbl {
12754 int max_pass;
12755 int table[32];
12757 static const struct percent_tbl e2fsck_tbl = {
12758 5, { 0, 70, 90, 92, 95, 100 }
12761 static char bar[128], spaces[128];
12763 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12764 int max)
12766 float percent;
12768 if (pass <= 0)
12769 return 0.0;
12770 if (pass > tbl->max_pass || max == 0)
12771 return 100.0;
12772 percent = ((float) curr) / ((float) max);
12773 return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12774 + tbl->table[pass-1]);
12777 void e2fsck_clear_progbar(e2fsck_t ctx)
12779 if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12780 return;
12782 printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12783 ctx->stop_meta);
12784 fflush(stdout);
12785 ctx->flags &= ~E2F_FLAG_PROG_BAR;
12788 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12789 unsigned int dpynum)
12791 static const char spinner[] = "\\|/-";
12792 int i;
12793 unsigned int tick;
12794 struct timeval tv;
12795 int dpywidth;
12796 int fixed_percent;
12798 if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12799 return 0;
12802 * Calculate the new progress position. If the
12803 * percentage hasn't changed, then we skip out right
12804 * away.
12806 fixed_percent = (int) ((10 * percent) + 0.5);
12807 if (ctx->progress_last_percent == fixed_percent)
12808 return 0;
12809 ctx->progress_last_percent = fixed_percent;
12812 * If we've already updated the spinner once within
12813 * the last 1/8th of a second, no point doing it
12814 * again.
12816 gettimeofday(&tv, NULL);
12817 tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12818 if ((tick == ctx->progress_last_time) &&
12819 (fixed_percent != 0) && (fixed_percent != 1000))
12820 return 0;
12821 ctx->progress_last_time = tick;
12824 * Advance the spinner, and note that the progress bar
12825 * will be on the screen
12827 ctx->progress_pos = (ctx->progress_pos+1) & 3;
12828 ctx->flags |= E2F_FLAG_PROG_BAR;
12830 dpywidth = 66 - strlen(label);
12831 dpywidth = 8 * (dpywidth / 8);
12832 if (dpynum)
12833 dpywidth -= 8;
12835 i = ((percent * dpywidth) + 50) / 100;
12836 printf("%s%s: |%s%s", ctx->start_meta, label,
12837 bar + (sizeof(bar) - (i+1)),
12838 spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12839 if (fixed_percent == 1000)
12840 bb_putchar('|');
12841 else
12842 bb_putchar(spinner[ctx->progress_pos & 3]);
12843 printf(" %4.1f%% ", percent);
12844 if (dpynum)
12845 printf("%u\r", dpynum);
12846 else
12847 fputs(" \r", stdout);
12848 fputs(ctx->stop_meta, stdout);
12850 if (fixed_percent == 1000)
12851 e2fsck_clear_progbar(ctx);
12852 fflush(stdout);
12854 return 0;
12857 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12858 unsigned long cur, unsigned long max)
12860 char buf[80];
12861 float percent;
12863 if (pass == 0)
12864 return 0;
12866 if (ctx->progress_fd) {
12867 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
12868 xwrite_str(ctx->progress_fd, buf);
12869 } else {
12870 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12871 e2fsck_simple_progress(ctx, ctx->device_name,
12872 percent, 0);
12874 return 0;
12877 static void reserve_stdio_fds(void)
12879 int fd;
12881 while (1) {
12882 fd = open(bb_dev_null, O_RDWR);
12883 if (fd > 2)
12884 break;
12885 if (fd < 0) {
12886 fprintf(stderr, _("ERROR: Cannot open "
12887 "/dev/null (%s)\n"),
12888 strerror(errno));
12889 break;
12892 close(fd);
12895 static void signal_progress_on(int sig FSCK_ATTR((unused)))
12897 e2fsck_t ctx = e2fsck_global_ctx;
12899 if (!ctx)
12900 return;
12902 ctx->progress = e2fsck_update_progress;
12903 ctx->progress_fd = 0;
12906 static void signal_progress_off(int sig FSCK_ATTR((unused)))
12908 e2fsck_t ctx = e2fsck_global_ctx;
12910 if (!ctx)
12911 return;
12913 e2fsck_clear_progbar(ctx);
12914 ctx->progress = 0;
12917 static void signal_cancel(int sig FSCK_ATTR((unused)))
12919 e2fsck_t ctx = e2fsck_global_ctx;
12921 if (!ctx)
12922 exit(FSCK_CANCELED);
12924 ctx->flags |= E2F_FLAG_CANCEL;
12927 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12929 char *buf, *token, *next, *p, *arg;
12930 int ea_ver;
12931 int extended_usage = 0;
12933 buf = string_copy(opts, 0);
12934 for (token = buf; token && *token; token = next) {
12935 p = strchr(token, ',');
12936 next = 0;
12937 if (p) {
12938 *p = 0;
12939 next = p+1;
12941 arg = strchr(token, '=');
12942 if (arg) {
12943 *arg = 0;
12944 arg++;
12946 if (strcmp(token, "ea_ver") == 0) {
12947 if (!arg) {
12948 extended_usage++;
12949 continue;
12951 ea_ver = strtoul(arg, &p, 0);
12952 if (*p ||
12953 ((ea_ver != 1) && (ea_ver != 2))) {
12954 fprintf(stderr,
12955 _("Invalid EA version.\n"));
12956 extended_usage++;
12957 continue;
12959 ctx->ext_attr_ver = ea_ver;
12960 } else {
12961 fprintf(stderr, _("Unknown extended option: %s\n"),
12962 token);
12963 extended_usage++;
12966 if (extended_usage) {
12967 bb_error_msg_and_die(
12968 "Extended options are separated by commas, "
12969 "and may take an argument which\n"
12970 "is set off by an equals ('=') sign. "
12971 "Valid extended options are:\n"
12972 "\tea_ver=<ea_version (1 or 2)>\n\n");
12977 static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
12979 int flush = 0;
12980 int c, fd;
12981 e2fsck_t ctx;
12982 errcode_t retval;
12983 struct sigaction sa;
12984 char *extended_opts = NULL;
12986 retval = e2fsck_allocate_context(&ctx);
12987 if (retval)
12988 return retval;
12990 *ret_ctx = ctx;
12992 setvbuf(stdout, NULL, _IONBF, BUFSIZ);
12993 setvbuf(stderr, NULL, _IONBF, BUFSIZ);
12994 if (isatty(0) && isatty(1)) {
12995 ctx->interactive = 1;
12996 } else {
12997 ctx->start_meta[0] = '\001';
12998 ctx->stop_meta[0] = '\002';
13000 memset(bar, '=', sizeof(bar)-1);
13001 memset(spaces, ' ', sizeof(spaces)-1);
13003 if (argc && *argv)
13004 ctx->program_name = *argv;
13005 else
13006 ctx->program_name = "e2fsck";
13007 while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
13008 switch (c) {
13009 case 'C':
13010 ctx->progress = e2fsck_update_progress;
13011 ctx->progress_fd = atoi(optarg);
13012 if (!ctx->progress_fd)
13013 break;
13014 /* Validate the file descriptor to avoid disasters */
13015 fd = dup(ctx->progress_fd);
13016 if (fd < 0) {
13017 fprintf(stderr,
13018 _("Error validating file descriptor %d: %s\n"),
13019 ctx->progress_fd,
13020 error_message(errno));
13021 bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13022 } else
13023 close(fd);
13024 break;
13025 case 'D':
13026 ctx->options |= E2F_OPT_COMPRESS_DIRS;
13027 break;
13028 case 'E':
13029 extended_opts = optarg;
13030 break;
13031 case 'p':
13032 case 'a':
13033 if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13034 conflict_opt:
13035 bb_error_msg_and_die(_("only one the options -p/-a, -n or -y may be specified"));
13037 ctx->options |= E2F_OPT_PREEN;
13038 break;
13039 case 'n':
13040 if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13041 goto conflict_opt;
13042 ctx->options |= E2F_OPT_NO;
13043 break;
13044 case 'y':
13045 if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13046 goto conflict_opt;
13047 ctx->options |= E2F_OPT_YES;
13048 break;
13049 case 't':
13050 /* FIXME - This needs to go away in a future path - will change binary */
13051 fprintf(stderr, _("The -t option is not "
13052 "supported on this version of e2fsck.\n"));
13053 break;
13054 case 'c':
13055 if (cflag++)
13056 ctx->options |= E2F_OPT_WRITECHECK;
13057 ctx->options |= E2F_OPT_CHECKBLOCKS;
13058 break;
13059 case 'r':
13060 /* What we do by default, anyway! */
13061 break;
13062 case 'b':
13063 ctx->use_superblock = atoi(optarg);
13064 ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13065 break;
13066 case 'B':
13067 ctx->blocksize = atoi(optarg);
13068 break;
13069 case 'I':
13070 ctx->inode_buffer_blocks = atoi(optarg);
13071 break;
13072 case 'j':
13073 ctx->journal_name = string_copy(optarg, 0);
13074 break;
13075 case 'P':
13076 ctx->process_inode_size = atoi(optarg);
13077 break;
13078 case 'd':
13079 ctx->options |= E2F_OPT_DEBUG;
13080 break;
13081 case 'f':
13082 ctx->options |= E2F_OPT_FORCE;
13083 break;
13084 case 'F':
13085 flush = 1;
13086 break;
13087 case 'v':
13088 verbose = 1;
13089 break;
13090 case 'V':
13091 show_version_only = 1;
13092 break;
13093 case 'N':
13094 ctx->device_name = optarg;
13095 break;
13096 #ifdef ENABLE_SWAPFS
13097 case 's':
13098 normalize_swapfs = 1;
13099 case 'S':
13100 swapfs = 1;
13101 break;
13102 #else
13103 case 's':
13104 case 'S':
13105 fprintf(stderr, _("Byte-swapping filesystems "
13106 "not compiled in this version "
13107 "of e2fsck\n"));
13108 exit(1);
13109 #endif
13110 default:
13111 bb_show_usage();
13113 if (show_version_only)
13114 return 0;
13115 if (optind != argc - 1)
13116 bb_show_usage();
13117 if ((ctx->options & E2F_OPT_NO) &&
13118 !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13119 ctx->options |= E2F_OPT_READONLY;
13120 ctx->io_options = strchr(argv[optind], '?');
13121 if (ctx->io_options)
13122 *ctx->io_options++ = 0;
13123 ctx->filesystem_name = argv[optind];
13124 if (resolve_mount_spec(&ctx->filesystem_name) < 0 ||
13125 !ctx->filesystem_name) {
13126 bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
13127 bb_error_msg_and_die(0);
13129 if (extended_opts)
13130 parse_extended_opts(ctx, extended_opts);
13132 if (flush) {
13133 fd = open(ctx->filesystem_name, O_RDONLY, 0);
13134 if (fd < 0) {
13135 bb_error_msg(_("while opening %s for flushing"),
13136 ctx->filesystem_name);
13137 bb_error_msg_and_die(0);
13139 if ((retval = ext2fs_sync_device(fd, 1))) {
13140 bb_error_msg(_("while trying to flush %s"),
13141 ctx->filesystem_name);
13142 bb_error_msg_and_die(0);
13144 close(fd);
13146 #ifdef ENABLE_SWAPFS
13147 if (swapfs && cflag) {
13148 fprintf(stderr, _("Incompatible options not "
13149 "allowed when byte-swapping.\n"));
13150 exit(EXIT_USAGE);
13152 #endif
13154 * Set up signal action
13156 memset(&sa, 0, sizeof(struct sigaction));
13157 sa.sa_handler = signal_cancel;
13158 sigaction(SIGINT, &sa, 0);
13159 sigaction(SIGTERM, &sa, 0);
13160 #ifdef SA_RESTART
13161 sa.sa_flags = SA_RESTART;
13162 #endif
13163 e2fsck_global_ctx = ctx;
13164 sa.sa_handler = signal_progress_on;
13165 sigaction(SIGUSR1, &sa, 0);
13166 sa.sa_handler = signal_progress_off;
13167 sigaction(SIGUSR2, &sa, 0);
13169 /* Update our PATH to include /sbin if we need to run badblocks */
13170 if (cflag)
13171 e2fs_set_sbin_path();
13172 return 0;
13175 static const char my_ver_string[] = E2FSPROGS_VERSION;
13176 static const char my_ver_date[] = E2FSPROGS_DATE;
13178 int e2fsck_main (int argc, char **argv);
13179 int e2fsck_main (int argc, char **argv)
13181 errcode_t retval;
13182 int exit_value = EXIT_OK;
13183 ext2_filsys fs = 0;
13184 io_manager io_ptr;
13185 struct ext2_super_block *sb;
13186 const char *lib_ver_date;
13187 int my_ver, lib_ver;
13188 e2fsck_t ctx;
13189 struct problem_context pctx;
13190 int flags, run_result;
13192 clear_problem_context(&pctx);
13194 my_ver = ext2fs_parse_version_string(my_ver_string);
13195 lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13196 if (my_ver > lib_ver) {
13197 fprintf( stderr, _("Error: ext2fs library version "
13198 "out of date!\n"));
13199 show_version_only++;
13202 retval = PRS(argc, argv, &ctx);
13203 if (retval) {
13204 bb_error_msg(_("while trying to initialize program"));
13205 exit(EXIT_ERROR);
13207 reserve_stdio_fds();
13209 if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13210 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13211 my_ver_date);
13213 if (show_version_only) {
13214 fprintf(stderr, _("\tUsing %s, %s\n"),
13215 error_message(EXT2_ET_BASE), lib_ver_date);
13216 exit(EXIT_OK);
13219 check_mount(ctx);
13221 if (!(ctx->options & E2F_OPT_PREEN) &&
13222 !(ctx->options & E2F_OPT_NO) &&
13223 !(ctx->options & E2F_OPT_YES)) {
13224 if (!ctx->interactive)
13225 bb_error_msg_and_die(_("need terminal for interactive repairs"));
13227 ctx->superblock = ctx->use_superblock;
13228 restart:
13229 #ifdef CONFIG_TESTIO_DEBUG
13230 io_ptr = test_io_manager;
13231 test_io_backing_manager = unix_io_manager;
13232 #else
13233 io_ptr = unix_io_manager;
13234 #endif
13235 flags = 0;
13236 if ((ctx->options & E2F_OPT_READONLY) == 0)
13237 flags |= EXT2_FLAG_RW;
13239 if (ctx->superblock && ctx->blocksize) {
13240 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13241 flags, ctx->superblock, ctx->blocksize,
13242 io_ptr, &fs);
13243 } else if (ctx->superblock) {
13244 int blocksize;
13245 for (blocksize = EXT2_MIN_BLOCK_SIZE;
13246 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13247 retval = ext2fs_open2(ctx->filesystem_name,
13248 ctx->io_options, flags,
13249 ctx->superblock, blocksize,
13250 io_ptr, &fs);
13251 if (!retval)
13252 break;
13254 } else
13255 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13256 flags, 0, 0, io_ptr, &fs);
13257 if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13258 !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13259 ((retval == EXT2_ET_BAD_MAGIC) ||
13260 ((retval == 0) && ext2fs_check_desc(fs)))) {
13261 if (!fs || (fs->group_desc_count > 1)) {
13262 printf(_("%s trying backup blocks...\n"),
13263 retval ? _("Couldn't find ext2 superblock,") :
13264 _("Group descriptors look bad..."));
13265 get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13266 if (fs)
13267 ext2fs_close(fs);
13268 goto restart;
13271 if (retval) {
13272 bb_error_msg(_("while trying to open %s"),
13273 ctx->filesystem_name);
13274 if (retval == EXT2_ET_REV_TOO_HIGH) {
13275 printf(_("The filesystem revision is apparently "
13276 "too high for this version of e2fsck.\n"
13277 "(Or the filesystem superblock "
13278 "is corrupt)\n\n"));
13279 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13280 } else if (retval == EXT2_ET_SHORT_READ)
13281 printf(_("Could this be a zero-length partition?\n"));
13282 else if ((retval == EPERM) || (retval == EACCES))
13283 printf(_("You must have %s access to the "
13284 "filesystem or be root\n"),
13285 (ctx->options & E2F_OPT_READONLY) ?
13286 "r/o" : "r/w");
13287 else if (retval == ENXIO)
13288 printf(_("Possibly non-existent or swap device?\n"));
13289 #ifdef EROFS
13290 else if (retval == EROFS)
13291 printf(_("Disk write-protected; use the -n option "
13292 "to do a read-only\n"
13293 "check of the device.\n"));
13294 #endif
13295 else
13296 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13297 bb_error_msg_and_die(0);
13299 ctx->fs = fs;
13300 fs->priv_data = ctx;
13301 sb = fs->super;
13302 if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13303 bb_error_msg(_("while trying to open %s"),
13304 ctx->filesystem_name);
13305 get_newer:
13306 bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13310 * Set the device name, which is used whenever we print error
13311 * or informational messages to the user.
13313 if (ctx->device_name == 0 &&
13314 (sb->s_volume_name[0] != 0)) {
13315 ctx->device_name = string_copy(sb->s_volume_name,
13316 sizeof(sb->s_volume_name));
13318 if (ctx->device_name == 0)
13319 ctx->device_name = ctx->filesystem_name;
13322 * Make sure the ext3 superblock fields are consistent.
13324 retval = e2fsck_check_ext3_journal(ctx);
13325 if (retval) {
13326 bb_error_msg(_("while checking ext3 journal for %s"),
13327 ctx->device_name);
13328 bb_error_msg_and_die(0);
13332 * Check to see if we need to do ext3-style recovery. If so,
13333 * do it, and then restart the fsck.
13335 if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13336 if (ctx->options & E2F_OPT_READONLY) {
13337 printf(_("Warning: skipping journal recovery "
13338 "because doing a read-only filesystem "
13339 "check.\n"));
13340 io_channel_flush(ctx->fs->io);
13341 } else {
13342 if (ctx->flags & E2F_FLAG_RESTARTED) {
13344 * Whoops, we attempted to run the
13345 * journal twice. This should never
13346 * happen, unless the hardware or
13347 * device driver is being bogus.
13349 bb_error_msg(_("can't set superblock flags on %s"), ctx->device_name);
13350 bb_error_msg_and_die(0);
13352 retval = e2fsck_run_ext3_journal(ctx);
13353 if (retval) {
13354 bb_error_msg(_("while recovering ext3 journal of %s"),
13355 ctx->device_name);
13356 bb_error_msg_and_die(0);
13358 ext2fs_close(ctx->fs);
13359 ctx->fs = 0;
13360 ctx->flags |= E2F_FLAG_RESTARTED;
13361 goto restart;
13366 * Check for compatibility with the feature sets. We need to
13367 * be more stringent than ext2fs_open().
13369 if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13370 (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13371 bb_error_msg("(%s)", ctx->device_name);
13372 goto get_newer;
13374 if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13375 bb_error_msg("(%s)", ctx->device_name);
13376 goto get_newer;
13378 #ifdef ENABLE_COMPRESSION
13379 /* FIXME - do we support this at all? */
13380 if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
13381 bb_error_msg(_("warning: compression support is experimental"));
13382 #endif
13383 #ifndef ENABLE_HTREE
13384 if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13385 bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13386 "but filesystem %s has HTREE directories."),
13387 ctx->device_name);
13388 goto get_newer;
13390 #endif
13393 * If the user specified a specific superblock, presumably the
13394 * master superblock has been trashed. So we mark the
13395 * superblock as dirty, so it can be written out.
13397 if (ctx->superblock &&
13398 !(ctx->options & E2F_OPT_READONLY))
13399 ext2fs_mark_super_dirty(fs);
13402 * We only update the master superblock because (a) paranoia;
13403 * we don't want to corrupt the backup superblocks, and (b) we
13404 * don't need to update the mount count and last checked
13405 * fields in the backup superblock (the kernel doesn't
13406 * update the backup superblocks anyway).
13408 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13410 ehandler_init(fs->io);
13412 if (ctx->superblock)
13413 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13414 ext2fs_mark_valid(fs);
13415 check_super_block(ctx);
13416 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13417 bb_error_msg_and_die(0);
13418 check_if_skip(ctx);
13419 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13420 bb_error_msg_and_die(0);
13421 #ifdef ENABLE_SWAPFS
13423 #ifdef WORDS_BIGENDIAN
13424 #define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13425 #else
13426 #define NATIVE_FLAG 0
13427 #endif
13430 if (normalize_swapfs) {
13431 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13432 fprintf(stderr, _("%s: Filesystem byte order "
13433 "already normalized.\n"), ctx->device_name);
13434 bb_error_msg_and_die(0);
13437 if (swapfs) {
13438 swap_filesys(ctx);
13439 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13440 bb_error_msg_and_die(0);
13442 #endif
13445 * Mark the system as valid, 'til proven otherwise
13447 ext2fs_mark_valid(fs);
13449 retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13450 if (retval) {
13451 bb_error_msg(_("while reading bad blocks inode"));
13452 preenhalt(ctx);
13453 printf(_("This doesn't bode well,"
13454 " but we'll try to go on...\n"));
13457 run_result = e2fsck_run(ctx);
13458 e2fsck_clear_progbar(ctx);
13459 if (run_result == E2F_FLAG_RESTART) {
13460 printf(_("Restarting e2fsck from the beginning...\n"));
13461 retval = e2fsck_reset_context(ctx);
13462 if (retval) {
13463 bb_error_msg(_("while resetting context"));
13464 bb_error_msg_and_die(0);
13466 ext2fs_close(fs);
13467 goto restart;
13469 if (run_result & E2F_FLAG_CANCEL) {
13470 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13471 ctx->device_name : ctx->filesystem_name);
13472 exit_value |= FSCK_CANCELED;
13474 if (run_result & E2F_FLAG_ABORT)
13475 bb_error_msg_and_die(_("aborted"));
13477 /* Cleanup */
13478 if (ext2fs_test_changed(fs)) {
13479 exit_value |= EXIT_NONDESTRUCT;
13480 if (!(ctx->options & E2F_OPT_PREEN))
13481 printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13482 ctx->device_name);
13483 if (ctx->mount_flags & EXT2_MF_ISROOT) {
13484 printf(_("%s: ***** REBOOT LINUX *****\n"),
13485 ctx->device_name);
13486 exit_value |= EXIT_DESTRUCT;
13489 if (!ext2fs_test_valid(fs)) {
13490 printf(_("\n%s: ********** WARNING: Filesystem still has "
13491 "errors **********\n\n"), ctx->device_name);
13492 exit_value |= EXIT_UNCORRECTED;
13493 exit_value &= ~EXIT_NONDESTRUCT;
13495 if (exit_value & FSCK_CANCELED)
13496 exit_value &= ~EXIT_NONDESTRUCT;
13497 else {
13498 show_stats(ctx);
13499 if (!(ctx->options & E2F_OPT_READONLY)) {
13500 if (ext2fs_test_valid(fs)) {
13501 if (!(sb->s_state & EXT2_VALID_FS))
13502 exit_value |= EXIT_NONDESTRUCT;
13503 sb->s_state = EXT2_VALID_FS;
13504 } else
13505 sb->s_state &= ~EXT2_VALID_FS;
13506 sb->s_mnt_count = 0;
13507 sb->s_lastcheck = time(NULL);
13508 ext2fs_mark_super_dirty(fs);
13512 e2fsck_write_bitmaps(ctx);
13514 ext2fs_close(fs);
13515 ctx->fs = NULL;
13516 free(ctx->filesystem_name);
13517 free(ctx->journal_name);
13518 e2fsck_free_context(ctx);
13520 return exit_value;