Changes to update Tomato RAF.
[tomato.git] / release / src / router / busybox / e2fsprogs / old_e2fsprogs / e2fsck.c
bloba40a9438f19aa58396d5751832e787fcfa66204f
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:
38 //usage:#define e2fsck_full_usage "\n\n"
39 //usage: "Check ext2/ext3 file system\n"
40 //usage: "\nOptions:"
41 //usage: "\n -p Automatic repair (no questions)"
42 //usage: "\n -n Make no changes to the filesystem"
43 //usage: "\n -y Assume 'yes' to all questions"
44 //usage: "\n -c Check for bad blocks and add them to the badblock list"
45 //usage: "\n -f Force checking even if filesystem is marked clean"
46 //usage: "\n -v Verbose"
47 //usage: "\n -b superblock Use alternative superblock"
48 //usage: "\n -B blocksize Force blocksize when looking for superblock"
49 //usage: "\n -j journal Set location of the external journal"
50 //usage: "\n -l file Add to badblocks list"
51 //usage: "\n -L file Set badblocks list"
52 //usage:
53 //applet:IF_E2FSCK(APPLET(e2fsck, _BB_DIR_SBIN, _BB_SUID_DROP))
54 //applet:IF_E2FSCK(APPLET_ODDNAME(fsck.ext2, e2fsck, _BB_DIR_SBIN, _BB_SUID_DROP, e2fsck))
55 //applet:IF_E2FSCK(APPLET_ODDNAME(fsck.ext3, e2fsck, _BB_DIR_SBIN, _BB_SUID_DROP, e2fsck))
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);
354 #if 0
356 * Verify that the tree contains the given node. This is done by
357 * traversing all of the nodes and comparing their pointers to the
358 * given pointer. Returns 1 if the node is found, otherwise
359 * returns zero. It is intended for debugging purposes.
362 static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
364 if (root != nil) {
365 return root == node
366 || verify_dict_has_node(nil, root->left, node)
367 || verify_dict_has_node(nil, root->right, node);
369 return 0;
371 #endif
374 * Select a different set of node allocator routines.
377 static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
379 assert(dict_count(dict) == 0);
380 dict->dict_freenode = fr;
384 * Free all the nodes in the dictionary by using the dictionary's
385 * installed free routine. The dictionary is emptied.
388 static void dict_free_nodes(dict_t *dict)
390 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
391 free_nodes(dict, root, nil);
392 dict->dict_nodecount = 0;
393 dict->nilnode.left = &dict->nilnode;
394 dict->nilnode.right = &dict->nilnode;
398 * Initialize a user-supplied dictionary object.
401 static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
403 dict->compare = comp;
404 dict->dict_freenode = dnode_free;
405 dict->dict_nodecount = 0;
406 dict->maxcount = maxcount;
407 dict->nilnode.left = &dict->nilnode;
408 dict->nilnode.right = &dict->nilnode;
409 dict->nilnode.parent = &dict->nilnode;
410 dict->nilnode.color = dnode_black;
411 dict->dupes = 0;
412 return dict;
416 * Locate a node in the dictionary having the given key.
417 * If the node is not found, a null a pointer is returned (rather than
418 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
419 * located node is returned.
422 static dnode_t *dict_lookup(dict_t *dict, const void *key)
424 dnode_t *root = dict_root(dict);
425 dnode_t *nil = dict_nil(dict);
426 dnode_t *saved;
427 int result;
429 /* simple binary search adapted for trees that contain duplicate keys */
431 while (root != nil) {
432 result = dict->compare(key, root->key);
433 if (result < 0)
434 root = root->left;
435 else if (result > 0)
436 root = root->right;
437 else {
438 if (!dict->dupes) { /* no duplicates, return match */
439 return root;
440 } else { /* could be dupes, find leftmost one */
441 do {
442 saved = root;
443 root = root->left;
444 while (root != nil && dict->compare(key, root->key))
445 root = root->right;
446 } while (root != nil);
447 return saved;
452 return NULL;
456 * Insert a node into the dictionary. The node should have been
457 * initialized with a data field. All other fields are ignored.
458 * The behavior is undefined if the user attempts to insert into
459 * a dictionary that is already full (for which the dict_isfull()
460 * function returns true).
463 static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
465 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
466 dnode_t *parent = nil, *uncle, *grandpa;
467 int result = -1;
469 node->key = key;
471 /* basic binary tree insert */
473 while (where != nil) {
474 parent = where;
475 result = dict->compare(key, where->key);
476 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
477 assert(dict->dupes || result != 0);
478 if (result < 0)
479 where = where->left;
480 else
481 where = where->right;
484 assert(where == nil);
486 if (result < 0)
487 parent->left = node;
488 else
489 parent->right = node;
491 node->parent = parent;
492 node->left = nil;
493 node->right = nil;
495 dict->dict_nodecount++;
497 /* red black adjustments */
499 node->color = dnode_red;
501 while (parent->color == dnode_red) {
502 grandpa = parent->parent;
503 if (parent == grandpa->left) {
504 uncle = grandpa->right;
505 if (uncle->color == dnode_red) { /* red parent, red uncle */
506 parent->color = dnode_black;
507 uncle->color = dnode_black;
508 grandpa->color = dnode_red;
509 node = grandpa;
510 parent = grandpa->parent;
511 } else { /* red parent, black uncle */
512 if (node == parent->right) {
513 rotate_left(parent);
514 parent = node;
515 assert (grandpa == parent->parent);
516 /* rotation between parent and child preserves grandpa */
518 parent->color = dnode_black;
519 grandpa->color = dnode_red;
520 rotate_right(grandpa);
521 break;
523 } else { /* symmetric cases: parent == parent->parent->right */
524 uncle = grandpa->left;
525 if (uncle->color == dnode_red) {
526 parent->color = dnode_black;
527 uncle->color = dnode_black;
528 grandpa->color = dnode_red;
529 node = grandpa;
530 parent = grandpa->parent;
531 } else {
532 if (node == parent->left) {
533 rotate_right(parent);
534 parent = node;
535 assert (grandpa == parent->parent);
537 parent->color = dnode_black;
538 grandpa->color = dnode_red;
539 rotate_left(grandpa);
540 break;
545 dict_root(dict)->color = dnode_black;
549 * Allocate a node using the dictionary's allocator routine, give it
550 * the data item.
553 static dnode_t *dnode_init(dnode_t *dnode, void *data)
555 dnode->data = data;
556 dnode->parent = NULL;
557 dnode->left = NULL;
558 dnode->right = NULL;
559 return dnode;
562 static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
564 dnode_t *node = xmalloc(sizeof(dnode_t));
566 dnode_init(node, data);
567 dict_insert(dict, node, key);
568 return 1;
572 * Return the node with the lowest (leftmost) key. If the dictionary is empty
573 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
576 static dnode_t *dict_first(dict_t *dict)
578 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
580 if (root != nil)
581 while ((left = root->left) != nil)
582 root = left;
584 return (root == nil) ? NULL : root;
588 * Return the given node's successor node---the node which has the
589 * next key in the the left to right ordering. If the node has
590 * no successor, a null pointer is returned rather than a pointer to
591 * the nil node.
594 static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
596 dnode_t *nil = dict_nil(dict), *parent, *left;
598 if (curr->right != nil) {
599 curr = curr->right;
600 while ((left = curr->left) != nil)
601 curr = left;
602 return curr;
605 parent = curr->parent;
607 while (parent != nil && curr == parent->right) {
608 curr = parent;
609 parent = curr->parent;
612 return (parent == nil) ? NULL : parent;
616 static void dnode_free(dnode_t *node)
618 free(node);
622 #undef left
623 #undef right
624 #undef parent
625 #undef color
626 #undef key
627 #undef data
629 #undef nilnode
630 #undef maxcount
631 #undef compare
632 #undef dupes
636 * dirinfo.c --- maintains the directory information table for e2fsck.
640 * This subroutine is called during pass1 to create a directory info
641 * entry. During pass1, the passed-in parent is 0; it will get filled
642 * in during pass2.
644 static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
646 struct dir_info *dir;
647 int i, j;
648 ext2_ino_t num_dirs;
649 errcode_t retval;
650 unsigned long old_size;
652 if (!ctx->dir_info) {
653 ctx->dir_info_count = 0;
654 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
655 if (retval)
656 num_dirs = 1024; /* Guess */
657 ctx->dir_info_size = num_dirs + 10;
658 ctx->dir_info = (struct dir_info *)
659 e2fsck_allocate_memory(ctx, ctx->dir_info_size
660 * sizeof (struct dir_info),
661 "directory map");
664 if (ctx->dir_info_count >= ctx->dir_info_size) {
665 old_size = ctx->dir_info_size * sizeof(struct dir_info);
666 ctx->dir_info_size += 10;
667 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
668 sizeof(struct dir_info),
669 &ctx->dir_info);
670 if (retval) {
671 ctx->dir_info_size -= 10;
672 return;
677 * Normally, add_dir_info is called with each inode in
678 * sequential order; but once in a while (like when pass 3
679 * needs to recreate the root directory or lost+found
680 * directory) it is called out of order. In those cases, we
681 * need to move the dir_info entries down to make room, since
682 * the dir_info array needs to be sorted by inode number for
683 * get_dir_info()'s sake.
685 if (ctx->dir_info_count &&
686 ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
687 for (i = ctx->dir_info_count-1; i > 0; i--)
688 if (ctx->dir_info[i-1].ino < ino)
689 break;
690 dir = &ctx->dir_info[i];
691 if (dir->ino != ino)
692 for (j = ctx->dir_info_count++; j > i; j--)
693 ctx->dir_info[j] = ctx->dir_info[j-1];
694 } else
695 dir = &ctx->dir_info[ctx->dir_info_count++];
697 dir->ino = ino;
698 dir->dotdot = parent;
699 dir->parent = parent;
703 * get_dir_info() --- given an inode number, try to find the directory
704 * information entry for it.
706 static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
708 int low, high, mid;
710 low = 0;
711 high = ctx->dir_info_count-1;
712 if (!ctx->dir_info)
713 return 0;
714 if (ino == ctx->dir_info[low].ino)
715 return &ctx->dir_info[low];
716 if (ino == ctx->dir_info[high].ino)
717 return &ctx->dir_info[high];
719 while (low < high) {
720 mid = (low+high)/2;
721 if (mid == low || mid == high)
722 break;
723 if (ino == ctx->dir_info[mid].ino)
724 return &ctx->dir_info[mid];
725 if (ino < ctx->dir_info[mid].ino)
726 high = mid;
727 else
728 low = mid;
730 return 0;
734 * Free the dir_info structure when it isn't needed any more.
736 static void e2fsck_free_dir_info(e2fsck_t ctx)
738 ext2fs_free_mem(&ctx->dir_info);
739 ctx->dir_info_size = 0;
740 ctx->dir_info_count = 0;
744 * Return the count of number of directories in the dir_info structure
746 static int e2fsck_get_num_dirinfo(e2fsck_t ctx)
748 return ctx->dir_info_count;
752 * A simple interator function
754 static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
756 if (*control >= ctx->dir_info_count)
757 return 0;
759 return ctx->dir_info + (*control)++;
763 * dirinfo.c --- maintains the directory information table for e2fsck.
767 #ifdef ENABLE_HTREE
770 * This subroutine is called during pass1 to create a directory info
771 * entry. During pass1, the passed-in parent is 0; it will get filled
772 * in during pass2.
774 static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
776 struct dx_dir_info *dir;
777 int i, j;
778 errcode_t retval;
779 unsigned long old_size;
781 if (!ctx->dx_dir_info) {
782 ctx->dx_dir_info_count = 0;
783 ctx->dx_dir_info_size = 100; /* Guess */
784 ctx->dx_dir_info = (struct dx_dir_info *)
785 e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
786 * sizeof (struct dx_dir_info),
787 "directory map");
790 if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
791 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
792 ctx->dx_dir_info_size += 10;
793 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
794 sizeof(struct dx_dir_info),
795 &ctx->dx_dir_info);
796 if (retval) {
797 ctx->dx_dir_info_size -= 10;
798 return;
803 * Normally, add_dx_dir_info is called with each inode in
804 * sequential order; but once in a while (like when pass 3
805 * needs to recreate the root directory or lost+found
806 * directory) it is called out of order. In those cases, we
807 * need to move the dx_dir_info entries down to make room, since
808 * the dx_dir_info array needs to be sorted by inode number for
809 * get_dx_dir_info()'s sake.
811 if (ctx->dx_dir_info_count &&
812 ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
813 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
814 if (ctx->dx_dir_info[i-1].ino < ino)
815 break;
816 dir = &ctx->dx_dir_info[i];
817 if (dir->ino != ino)
818 for (j = ctx->dx_dir_info_count++; j > i; j--)
819 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
820 } else
821 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
823 dir->ino = ino;
824 dir->numblocks = num_blocks;
825 dir->hashversion = 0;
826 dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
827 * sizeof (struct dx_dirblock_info),
828 "dx_block info array");
832 * get_dx_dir_info() --- given an inode number, try to find the directory
833 * information entry for it.
835 static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
837 int low, high, mid;
839 low = 0;
840 high = ctx->dx_dir_info_count-1;
841 if (!ctx->dx_dir_info)
842 return 0;
843 if (ino == ctx->dx_dir_info[low].ino)
844 return &ctx->dx_dir_info[low];
845 if (ino == ctx->dx_dir_info[high].ino)
846 return &ctx->dx_dir_info[high];
848 while (low < high) {
849 mid = (low+high)/2;
850 if (mid == low || mid == high)
851 break;
852 if (ino == ctx->dx_dir_info[mid].ino)
853 return &ctx->dx_dir_info[mid];
854 if (ino < ctx->dx_dir_info[mid].ino)
855 high = mid;
856 else
857 low = mid;
859 return 0;
863 * Free the dx_dir_info structure when it isn't needed any more.
865 static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
867 int i;
868 struct dx_dir_info *dir;
870 if (ctx->dx_dir_info) {
871 dir = ctx->dx_dir_info;
872 for (i=0; i < ctx->dx_dir_info_count; i++) {
873 ext2fs_free_mem(&dir->dx_block);
875 ext2fs_free_mem(&ctx->dx_dir_info);
877 ctx->dx_dir_info_size = 0;
878 ctx->dx_dir_info_count = 0;
882 * A simple interator function
884 static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
886 if (*control >= ctx->dx_dir_info_count)
887 return 0;
889 return ctx->dx_dir_info + (*control)++;
892 #endif /* ENABLE_HTREE */
894 * e2fsck.c - a consistency checker for the new extended file system.
899 * This function allocates an e2fsck context
901 static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
903 e2fsck_t context;
904 errcode_t retval;
906 retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
907 if (retval)
908 return retval;
910 memset(context, 0, sizeof(struct e2fsck_struct));
912 context->process_inode_size = 256;
913 context->ext_attr_ver = 2;
915 *ret = context;
916 return 0;
919 struct ea_refcount_el {
920 blk_t ea_blk;
921 int ea_count;
924 struct ea_refcount {
925 blk_t count;
926 blk_t size;
927 blk_t cursor;
928 struct ea_refcount_el *list;
931 static void ea_refcount_free(ext2_refcount_t refcount)
933 if (!refcount)
934 return;
936 ext2fs_free_mem(&refcount->list);
937 ext2fs_free_mem(&refcount);
941 * This function resets an e2fsck context; it is called when e2fsck
942 * needs to be restarted.
944 static errcode_t e2fsck_reset_context(e2fsck_t ctx)
946 ctx->flags = 0;
947 ctx->lost_and_found = 0;
948 ctx->bad_lost_and_found = 0;
949 ext2fs_free_inode_bitmap(ctx->inode_used_map);
950 ctx->inode_used_map = 0;
951 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
952 ctx->inode_dir_map = 0;
953 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
954 ctx->inode_reg_map = 0;
955 ext2fs_free_block_bitmap(ctx->block_found_map);
956 ctx->block_found_map = 0;
957 ext2fs_free_icount(ctx->inode_link_info);
958 ctx->inode_link_info = 0;
959 if (ctx->journal_io) {
960 if (ctx->fs && ctx->fs->io != ctx->journal_io)
961 io_channel_close(ctx->journal_io);
962 ctx->journal_io = 0;
964 if (ctx->fs) {
965 ext2fs_free_dblist(ctx->fs->dblist);
966 ctx->fs->dblist = 0;
968 e2fsck_free_dir_info(ctx);
969 #ifdef ENABLE_HTREE
970 e2fsck_free_dx_dir_info(ctx);
971 #endif
972 ea_refcount_free(ctx->refcount);
973 ctx->refcount = 0;
974 ea_refcount_free(ctx->refcount_extra);
975 ctx->refcount_extra = 0;
976 ext2fs_free_block_bitmap(ctx->block_dup_map);
977 ctx->block_dup_map = 0;
978 ext2fs_free_block_bitmap(ctx->block_ea_map);
979 ctx->block_ea_map = 0;
980 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
981 ctx->inode_bad_map = 0;
982 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
983 ctx->inode_imagic_map = 0;
984 ext2fs_u32_list_free(ctx->dirs_to_hash);
985 ctx->dirs_to_hash = 0;
988 * Clear the array of invalid meta-data flags
990 ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
991 ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
992 ext2fs_free_mem(&ctx->invalid_inode_table_flag);
994 /* Clear statistic counters */
995 ctx->fs_directory_count = 0;
996 ctx->fs_regular_count = 0;
997 ctx->fs_blockdev_count = 0;
998 ctx->fs_chardev_count = 0;
999 ctx->fs_links_count = 0;
1000 ctx->fs_symlinks_count = 0;
1001 ctx->fs_fast_symlinks_count = 0;
1002 ctx->fs_fifo_count = 0;
1003 ctx->fs_total_count = 0;
1004 ctx->fs_sockets_count = 0;
1005 ctx->fs_ind_count = 0;
1006 ctx->fs_dind_count = 0;
1007 ctx->fs_tind_count = 0;
1008 ctx->fs_fragmented = 0;
1009 ctx->large_files = 0;
1011 /* Reset the superblock to the user's requested value */
1012 ctx->superblock = ctx->use_superblock;
1014 return 0;
1017 static void e2fsck_free_context(e2fsck_t ctx)
1019 if (!ctx)
1020 return;
1022 e2fsck_reset_context(ctx);
1024 ext2fs_free_mem(&ctx);
1028 * ea_refcount.c
1032 * The strategy we use for keeping track of EA refcounts is as
1033 * follows. We keep a sorted array of first EA blocks and its
1034 * reference counts. Once the refcount has dropped to zero, it is
1035 * removed from the array to save memory space. Once the EA block is
1036 * checked, its bit is set in the block_ea_map bitmap.
1040 static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
1042 ext2_refcount_t refcount;
1043 errcode_t retval;
1044 size_t bytes;
1046 retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
1047 if (retval)
1048 return retval;
1049 memset(refcount, 0, sizeof(struct ea_refcount));
1051 if (!size)
1052 size = 500;
1053 refcount->size = size;
1054 bytes = (size_t) (size * sizeof(struct ea_refcount_el));
1055 #ifdef DEBUG
1056 printf("Refcount allocated %d entries, %d bytes.\n",
1057 refcount->size, bytes);
1058 #endif
1059 retval = ext2fs_get_mem(bytes, &refcount->list);
1060 if (retval)
1061 goto errout;
1062 memset(refcount->list, 0, bytes);
1064 refcount->count = 0;
1065 refcount->cursor = 0;
1067 *ret = refcount;
1068 return 0;
1070 errout:
1071 ea_refcount_free(refcount);
1072 return retval;
1076 * collapse_refcount() --- go through the refcount array, and get rid
1077 * of any count == zero entries
1079 static void refcount_collapse(ext2_refcount_t refcount)
1081 unsigned int i, j;
1082 struct ea_refcount_el *list;
1084 list = refcount->list;
1085 for (i = 0, j = 0; i < refcount->count; i++) {
1086 if (list[i].ea_count) {
1087 if (i != j)
1088 list[j] = list[i];
1089 j++;
1092 #if defined(DEBUG) || defined(TEST_PROGRAM)
1093 printf("Refcount_collapse: size was %d, now %d\n",
1094 refcount->count, j);
1095 #endif
1096 refcount->count = j;
1101 * insert_refcount_el() --- Insert a new entry into the sorted list at a
1102 * specified position.
1104 static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
1105 blk_t blk, int pos)
1107 struct ea_refcount_el *el;
1108 errcode_t retval;
1109 blk_t new_size = 0;
1110 int num;
1112 if (refcount->count >= refcount->size) {
1113 new_size = refcount->size + 100;
1114 #ifdef DEBUG
1115 printf("Reallocating refcount %d entries...\n", new_size);
1116 #endif
1117 retval = ext2fs_resize_mem((size_t) refcount->size *
1118 sizeof(struct ea_refcount_el),
1119 (size_t) new_size *
1120 sizeof(struct ea_refcount_el),
1121 &refcount->list);
1122 if (retval)
1123 return 0;
1124 refcount->size = new_size;
1126 num = (int) refcount->count - pos;
1127 if (num < 0)
1128 return 0; /* should never happen */
1129 if (num) {
1130 memmove(&refcount->list[pos+1], &refcount->list[pos],
1131 sizeof(struct ea_refcount_el) * num);
1133 refcount->count++;
1134 el = &refcount->list[pos];
1135 el->ea_count = 0;
1136 el->ea_blk = blk;
1137 return el;
1142 * get_refcount_el() --- given an block number, try to find refcount
1143 * information in the sorted list. If the create flag is set,
1144 * and we can't find an entry, create one in the sorted list.
1146 static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
1147 blk_t blk, int create)
1149 float range;
1150 int low, high, mid;
1151 blk_t lowval, highval;
1153 if (!refcount || !refcount->list)
1154 return 0;
1155 retry:
1156 low = 0;
1157 high = (int) refcount->count-1;
1158 if (create && ((refcount->count == 0) ||
1159 (blk > refcount->list[high].ea_blk))) {
1160 if (refcount->count >= refcount->size)
1161 refcount_collapse(refcount);
1163 return insert_refcount_el(refcount, blk,
1164 (unsigned) refcount->count);
1166 if (refcount->count == 0)
1167 return 0;
1169 if (refcount->cursor >= refcount->count)
1170 refcount->cursor = 0;
1171 if (blk == refcount->list[refcount->cursor].ea_blk)
1172 return &refcount->list[refcount->cursor++];
1173 #ifdef DEBUG
1174 printf("Non-cursor get_refcount_el: %u\n", blk);
1175 #endif
1176 while (low <= high) {
1177 if (low == high)
1178 mid = low;
1179 else {
1180 /* Interpolate for efficiency */
1181 lowval = refcount->list[low].ea_blk;
1182 highval = refcount->list[high].ea_blk;
1184 if (blk < lowval)
1185 range = 0;
1186 else if (blk > highval)
1187 range = 1;
1188 else
1189 range = ((float) (blk - lowval)) /
1190 (highval - lowval);
1191 mid = low + ((int) (range * (high-low)));
1194 if (blk == refcount->list[mid].ea_blk) {
1195 refcount->cursor = mid+1;
1196 return &refcount->list[mid];
1198 if (blk < refcount->list[mid].ea_blk)
1199 high = mid-1;
1200 else
1201 low = mid+1;
1204 * If we need to create a new entry, it should be right at
1205 * low (where high will be left at low-1).
1207 if (create) {
1208 if (refcount->count >= refcount->size) {
1209 refcount_collapse(refcount);
1210 if (refcount->count < refcount->size)
1211 goto retry;
1213 return insert_refcount_el(refcount, blk, low);
1215 return 0;
1218 static errcode_t
1219 ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
1221 struct ea_refcount_el *el;
1223 el = get_refcount_el(refcount, blk, 1);
1224 if (!el)
1225 return EXT2_ET_NO_MEMORY;
1226 el->ea_count++;
1228 if (ret)
1229 *ret = el->ea_count;
1230 return 0;
1233 static errcode_t
1234 ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
1236 struct ea_refcount_el *el;
1238 el = get_refcount_el(refcount, blk, 0);
1239 if (!el || el->ea_count == 0)
1240 return EXT2_ET_INVALID_ARGUMENT;
1242 el->ea_count--;
1244 if (ret)
1245 *ret = el->ea_count;
1246 return 0;
1249 static errcode_t
1250 ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
1252 struct ea_refcount_el *el;
1255 * Get the refcount element
1257 el = get_refcount_el(refcount, blk, count ? 1 : 0);
1258 if (!el)
1259 return count ? EXT2_ET_NO_MEMORY : 0;
1260 el->ea_count = count;
1261 return 0;
1264 static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
1266 refcount->cursor = 0;
1270 static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
1272 struct ea_refcount_el *list;
1274 while (1) {
1275 if (refcount->cursor >= refcount->count)
1276 return 0;
1277 list = refcount->list;
1278 if (list[refcount->cursor].ea_count) {
1279 if (ret)
1280 *ret = list[refcount->cursor].ea_count;
1281 return list[refcount->cursor++].ea_blk;
1283 refcount->cursor++;
1289 * ehandler.c --- handle bad block errors which come up during the
1290 * course of an e2fsck session.
1294 static const char *operation;
1296 static errcode_t
1297 e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
1298 void *data, size_t size FSCK_ATTR((unused)),
1299 int actual FSCK_ATTR((unused)), errcode_t error)
1301 int i;
1302 char *p;
1303 ext2_filsys fs = (ext2_filsys) channel->app_data;
1304 e2fsck_t ctx;
1306 ctx = (e2fsck_t) fs->priv_data;
1309 * If more than one block was read, try reading each block
1310 * separately. We could use the actual bytes read to figure
1311 * out where to start, but we don't bother.
1313 if (count > 1) {
1314 p = (char *) data;
1315 for (i=0; i < count; i++, p += channel->block_size, block++) {
1316 error = io_channel_read_blk(channel, block,
1317 1, p);
1318 if (error)
1319 return error;
1321 return 0;
1323 if (operation)
1324 printf(_("Error reading block %lu (%s) while %s. "), block,
1325 error_message(error), operation);
1326 else
1327 printf(_("Error reading block %lu (%s). "), block,
1328 error_message(error));
1329 preenhalt(ctx);
1330 if (ask(ctx, _("Ignore error"), 1)) {
1331 if (ask(ctx, _("Force rewrite"), 1))
1332 io_channel_write_blk(channel, block, 1, data);
1333 return 0;
1336 return error;
1339 static errcode_t
1340 e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
1341 const void *data, size_t size FSCK_ATTR((unused)),
1342 int actual FSCK_ATTR((unused)), errcode_t error)
1344 int i;
1345 const char *p;
1346 ext2_filsys fs = (ext2_filsys) channel->app_data;
1347 e2fsck_t ctx;
1349 ctx = (e2fsck_t) fs->priv_data;
1352 * If more than one block was written, try writing each block
1353 * separately. We could use the actual bytes read to figure
1354 * out where to start, but we don't bother.
1356 if (count > 1) {
1357 p = (const char *) data;
1358 for (i=0; i < count; i++, p += channel->block_size, block++) {
1359 error = io_channel_write_blk(channel, block,
1360 1, p);
1361 if (error)
1362 return error;
1364 return 0;
1367 if (operation)
1368 printf(_("Error writing block %lu (%s) while %s. "), block,
1369 error_message(error), operation);
1370 else
1371 printf(_("Error writing block %lu (%s). "), block,
1372 error_message(error));
1373 preenhalt(ctx);
1374 if (ask(ctx, _("Ignore error"), 1))
1375 return 0;
1377 return error;
1380 static const char *ehandler_operation(const char *op)
1382 const char *ret = operation;
1384 operation = op;
1385 return ret;
1388 static void ehandler_init(io_channel channel)
1390 channel->read_error = e2fsck_handle_read_error;
1391 channel->write_error = e2fsck_handle_write_error;
1395 * journal.c --- code for handling the "ext3" journal
1397 * Copyright (C) 2000 Andreas Dilger
1398 * Copyright (C) 2000 Theodore Ts'o
1400 * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
1401 * Copyright (C) 1999 Red Hat Software
1403 * This file may be redistributed under the terms of the
1404 * GNU General Public License version 2 or at your discretion
1405 * any later version.
1409 * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
1410 * This creates a larger static binary, and a smaller binary using
1411 * shared libraries. It's also probably slightly less CPU-efficient,
1412 * which is why it's not on by default. But, it's a good way of
1413 * testing the functions in inode_io.c and fileio.c.
1415 #undef USE_INODE_IO
1417 /* Kernel compatibility functions for handling the journal. These allow us
1418 * to use the recovery.c file virtually unchanged from the kernel, so we
1419 * don't have to do much to keep kernel and user recovery in sync.
1421 static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
1423 #ifdef USE_INODE_IO
1424 *phys = block;
1425 return 0;
1426 #else
1427 struct inode *inode = journal->j_inode;
1428 errcode_t retval;
1429 blk_t pblk;
1431 if (!inode) {
1432 *phys = block;
1433 return 0;
1436 retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
1437 &inode->i_ext2, NULL, 0, block, &pblk);
1438 *phys = pblk;
1439 return retval;
1440 #endif
1443 static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
1445 struct buffer_head *bh;
1447 bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
1448 if (!bh)
1449 return NULL;
1451 bh->b_ctx = kdev->k_ctx;
1452 if (kdev->k_dev == K_DEV_FS)
1453 bh->b_io = kdev->k_ctx->fs->io;
1454 else
1455 bh->b_io = kdev->k_ctx->journal_io;
1456 bh->b_size = blocksize;
1457 bh->b_blocknr = blocknr;
1459 return bh;
1462 static void sync_blockdev(kdev_t kdev)
1464 io_channel io;
1466 if (kdev->k_dev == K_DEV_FS)
1467 io = kdev->k_ctx->fs->io;
1468 else
1469 io = kdev->k_ctx->journal_io;
1471 io_channel_flush(io);
1474 static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
1476 int retval;
1477 struct buffer_head *bh;
1479 for (; nr > 0; --nr) {
1480 bh = *bhp++;
1481 if (rw == READ && !bh->b_uptodate) {
1482 retval = io_channel_read_blk(bh->b_io,
1483 bh->b_blocknr,
1484 1, bh->b_data);
1485 if (retval) {
1486 bb_error_msg("while reading block %lu",
1487 (unsigned long) bh->b_blocknr);
1488 bh->b_err = retval;
1489 continue;
1491 bh->b_uptodate = 1;
1492 } else if (rw == WRITE && bh->b_dirty) {
1493 retval = io_channel_write_blk(bh->b_io,
1494 bh->b_blocknr,
1495 1, bh->b_data);
1496 if (retval) {
1497 bb_error_msg("while writing block %lu",
1498 (unsigned long) bh->b_blocknr);
1499 bh->b_err = retval;
1500 continue;
1502 bh->b_dirty = 0;
1503 bh->b_uptodate = 1;
1508 static void mark_buffer_dirty(struct buffer_head *bh)
1510 bh->b_dirty = 1;
1513 static inline void mark_buffer_clean(struct buffer_head * bh)
1515 bh->b_dirty = 0;
1518 static void brelse(struct buffer_head *bh)
1520 if (bh->b_dirty)
1521 ll_rw_block(WRITE, 1, &bh);
1522 ext2fs_free_mem(&bh);
1525 static int buffer_uptodate(struct buffer_head *bh)
1527 return bh->b_uptodate;
1530 static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
1532 bh->b_uptodate = val;
1535 static void wait_on_buffer(struct buffer_head *bh)
1537 if (!bh->b_uptodate)
1538 ll_rw_block(READ, 1, &bh);
1542 static void e2fsck_clear_recover(e2fsck_t ctx, int error)
1544 ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
1546 /* if we had an error doing journal recovery, we need a full fsck */
1547 if (error)
1548 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
1549 ext2fs_mark_super_dirty(ctx->fs);
1552 static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
1554 struct ext2_super_block *sb = ctx->fs->super;
1555 struct ext2_super_block jsuper;
1556 struct problem_context pctx;
1557 struct buffer_head *bh;
1558 struct inode *j_inode = NULL;
1559 struct kdev_s *dev_fs = NULL, *dev_journal;
1560 const char *journal_name = NULL;
1561 journal_t *journal = NULL;
1562 errcode_t retval = 0;
1563 io_manager io_ptr = 0;
1564 unsigned long start = 0;
1565 blk_t blk;
1566 int ext_journal = 0;
1567 int tried_backup_jnl = 0;
1568 int i;
1570 clear_problem_context(&pctx);
1572 journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
1573 if (!journal) {
1574 return EXT2_ET_NO_MEMORY;
1577 dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
1578 if (!dev_fs) {
1579 retval = EXT2_ET_NO_MEMORY;
1580 goto errout;
1582 dev_journal = dev_fs+1;
1584 dev_fs->k_ctx = dev_journal->k_ctx = ctx;
1585 dev_fs->k_dev = K_DEV_FS;
1586 dev_journal->k_dev = K_DEV_JOURNAL;
1588 journal->j_dev = dev_journal;
1589 journal->j_fs_dev = dev_fs;
1590 journal->j_inode = NULL;
1591 journal->j_blocksize = ctx->fs->blocksize;
1593 if (uuid_is_null(sb->s_journal_uuid)) {
1594 if (!sb->s_journal_inum)
1595 return EXT2_ET_BAD_INODE_NUM;
1596 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
1597 "journal inode");
1598 if (!j_inode) {
1599 retval = EXT2_ET_NO_MEMORY;
1600 goto errout;
1603 j_inode->i_ctx = ctx;
1604 j_inode->i_ino = sb->s_journal_inum;
1606 if ((retval = ext2fs_read_inode(ctx->fs,
1607 sb->s_journal_inum,
1608 &j_inode->i_ext2))) {
1609 try_backup_journal:
1610 if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
1611 tried_backup_jnl)
1612 goto errout;
1613 memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
1614 memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
1615 EXT2_N_BLOCKS*4);
1616 j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
1617 j_inode->i_ext2.i_links_count = 1;
1618 j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
1619 tried_backup_jnl++;
1621 if (!j_inode->i_ext2.i_links_count ||
1622 !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
1623 retval = EXT2_ET_NO_JOURNAL;
1624 goto try_backup_journal;
1626 if (j_inode->i_ext2.i_size / journal->j_blocksize <
1627 JFS_MIN_JOURNAL_BLOCKS) {
1628 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1629 goto try_backup_journal;
1631 for (i=0; i < EXT2_N_BLOCKS; i++) {
1632 blk = j_inode->i_ext2.i_block[i];
1633 if (!blk) {
1634 if (i < EXT2_NDIR_BLOCKS) {
1635 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1636 goto try_backup_journal;
1638 continue;
1640 if (blk < sb->s_first_data_block ||
1641 blk >= sb->s_blocks_count) {
1642 retval = EXT2_ET_BAD_BLOCK_NUM;
1643 goto try_backup_journal;
1646 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
1648 #ifdef USE_INODE_IO
1649 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
1650 &j_inode->i_ext2,
1651 &journal_name);
1652 if (retval)
1653 goto errout;
1655 io_ptr = inode_io_manager;
1656 #else
1657 journal->j_inode = j_inode;
1658 ctx->journal_io = ctx->fs->io;
1659 if ((retval = journal_bmap(journal, 0, &start)) != 0)
1660 goto errout;
1661 #endif
1662 } else {
1663 ext_journal = 1;
1664 if (!ctx->journal_name) {
1665 char uuid[37];
1667 unparse_uuid(sb->s_journal_uuid, uuid);
1668 ctx->journal_name = get_devname_from_uuid(uuid);
1669 if (!ctx->journal_name)
1670 ctx->journal_name = get_devname_from_device(sb->s_journal_dev);
1672 journal_name = ctx->journal_name;
1674 if (!journal_name) {
1675 fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
1676 return EXT2_ET_LOAD_EXT_JOURNAL;
1679 io_ptr = unix_io_manager;
1682 #ifndef USE_INODE_IO
1683 if (ext_journal)
1684 #endif
1685 retval = io_ptr->open(journal_name, IO_FLAG_RW,
1686 &ctx->journal_io);
1687 if (retval)
1688 goto errout;
1690 io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
1692 if (ext_journal) {
1693 if (ctx->fs->blocksize == 1024)
1694 start = 1;
1695 bh = getblk(dev_journal, start, ctx->fs->blocksize);
1696 if (!bh) {
1697 retval = EXT2_ET_NO_MEMORY;
1698 goto errout;
1700 ll_rw_block(READ, 1, &bh);
1701 if ((retval = bh->b_err) != 0)
1702 goto errout;
1703 memcpy(&jsuper, start ? bh->b_data : bh->b_data + 1024,
1704 sizeof(jsuper));
1705 brelse(bh);
1706 #if BB_BIG_ENDIAN
1707 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
1708 ext2fs_swap_super(&jsuper);
1709 #endif
1710 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
1711 !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
1712 fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
1713 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1714 goto errout;
1716 /* Make sure the journal UUID is correct */
1717 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
1718 sizeof(jsuper.s_uuid))) {
1719 fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
1720 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1721 goto errout;
1724 journal->j_maxlen = jsuper.s_blocks_count;
1725 start++;
1728 if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
1729 retval = EXT2_ET_NO_MEMORY;
1730 goto errout;
1733 journal->j_sb_buffer = bh;
1734 journal->j_superblock = (journal_superblock_t *)bh->b_data;
1736 #ifdef USE_INODE_IO
1737 ext2fs_free_mem(&j_inode);
1738 #endif
1740 *ret_journal = journal;
1741 return 0;
1743 errout:
1744 ext2fs_free_mem(&dev_fs);
1745 ext2fs_free_mem(&j_inode);
1746 ext2fs_free_mem(&journal);
1747 return retval;
1750 static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
1751 struct problem_context *pctx)
1753 struct ext2_super_block *sb = ctx->fs->super;
1754 int recover = ctx->fs->super->s_feature_incompat &
1755 EXT3_FEATURE_INCOMPAT_RECOVER;
1756 int has_journal = ctx->fs->super->s_feature_compat &
1757 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1759 if (has_journal || sb->s_journal_inum) {
1760 /* The journal inode is bogus, remove and force full fsck */
1761 pctx->ino = sb->s_journal_inum;
1762 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
1763 if (has_journal && sb->s_journal_inum)
1764 printf("*** ext3 journal has been deleted - "
1765 "filesystem is now ext2 only ***\n\n");
1766 sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1767 sb->s_journal_inum = 0;
1768 ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
1769 e2fsck_clear_recover(ctx, 1);
1770 return 0;
1772 return EXT2_ET_BAD_INODE_NUM;
1773 } else if (recover) {
1774 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
1775 e2fsck_clear_recover(ctx, 1);
1776 return 0;
1778 return EXT2_ET_UNSUPP_FEATURE;
1780 return 0;
1783 #define V1_SB_SIZE 0x0024
1784 static void clear_v2_journal_fields(journal_t *journal)
1786 e2fsck_t ctx = journal->j_dev->k_ctx;
1787 struct problem_context pctx;
1789 clear_problem_context(&pctx);
1791 if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
1792 return;
1794 memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
1795 ctx->fs->blocksize-V1_SB_SIZE);
1796 mark_buffer_dirty(journal->j_sb_buffer);
1800 static errcode_t e2fsck_journal_load(journal_t *journal)
1802 e2fsck_t ctx = journal->j_dev->k_ctx;
1803 journal_superblock_t *jsb;
1804 struct buffer_head *jbh = journal->j_sb_buffer;
1805 struct problem_context pctx;
1807 clear_problem_context(&pctx);
1809 ll_rw_block(READ, 1, &jbh);
1810 if (jbh->b_err) {
1811 bb_error_msg(_("reading journal superblock"));
1812 return jbh->b_err;
1815 jsb = journal->j_superblock;
1816 /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
1817 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
1818 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1820 switch (ntohl(jsb->s_header.h_blocktype)) {
1821 case JFS_SUPERBLOCK_V1:
1822 journal->j_format_version = 1;
1823 if (jsb->s_feature_compat ||
1824 jsb->s_feature_incompat ||
1825 jsb->s_feature_ro_compat ||
1826 jsb->s_nr_users)
1827 clear_v2_journal_fields(journal);
1828 break;
1830 case JFS_SUPERBLOCK_V2:
1831 journal->j_format_version = 2;
1832 if (ntohl(jsb->s_nr_users) > 1 &&
1833 uuid_is_null(ctx->fs->super->s_journal_uuid))
1834 clear_v2_journal_fields(journal);
1835 if (ntohl(jsb->s_nr_users) > 1) {
1836 fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
1837 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1839 break;
1842 * These should never appear in a journal super block, so if
1843 * they do, the journal is badly corrupted.
1845 case JFS_DESCRIPTOR_BLOCK:
1846 case JFS_COMMIT_BLOCK:
1847 case JFS_REVOKE_BLOCK:
1848 return EXT2_ET_CORRUPT_SUPERBLOCK;
1850 /* If we don't understand the superblock major type, but there
1851 * is a magic number, then it is likely to be a new format we
1852 * just don't understand, so leave it alone. */
1853 default:
1854 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1857 if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
1858 return EXT2_ET_UNSUPP_FEATURE;
1860 if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
1861 return EXT2_ET_RO_UNSUPP_FEATURE;
1863 /* We have now checked whether we know enough about the journal
1864 * format to be able to proceed safely, so any other checks that
1865 * fail we should attempt to recover from. */
1866 if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
1867 bb_error_msg(_("%s: no valid journal superblock found"),
1868 ctx->device_name);
1869 return EXT2_ET_CORRUPT_SUPERBLOCK;
1872 if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
1873 journal->j_maxlen = ntohl(jsb->s_maxlen);
1874 else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
1875 bb_error_msg(_("%s: journal too short"),
1876 ctx->device_name);
1877 return EXT2_ET_CORRUPT_SUPERBLOCK;
1880 journal->j_tail_sequence = ntohl(jsb->s_sequence);
1881 journal->j_transaction_sequence = journal->j_tail_sequence;
1882 journal->j_tail = ntohl(jsb->s_start);
1883 journal->j_first = ntohl(jsb->s_first);
1884 journal->j_last = ntohl(jsb->s_maxlen);
1886 return 0;
1889 static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
1890 journal_t *journal)
1892 char *p;
1893 union {
1894 __u8 uuid[16];
1895 __u32 val[4];
1896 } u;
1897 __u32 new_seq = 0;
1898 int i;
1900 /* Leave a valid existing V1 superblock signature alone.
1901 * Anything unrecognizable we overwrite with a new V2
1902 * signature. */
1904 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
1905 jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
1906 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
1907 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
1910 /* Zero out everything else beyond the superblock header */
1912 p = ((char *) jsb) + sizeof(journal_header_t);
1913 memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
1915 jsb->s_blocksize = htonl(ctx->fs->blocksize);
1916 jsb->s_maxlen = htonl(journal->j_maxlen);
1917 jsb->s_first = htonl(1);
1919 /* Initialize the journal sequence number so that there is "no"
1920 * chance we will find old "valid" transactions in the journal.
1921 * This avoids the need to zero the whole journal (slow to do,
1922 * and risky when we are just recovering the filesystem).
1924 generate_uuid(u.uuid);
1925 for (i = 0; i < 4; i ++)
1926 new_seq ^= u.val[i];
1927 jsb->s_sequence = htonl(new_seq);
1929 mark_buffer_dirty(journal->j_sb_buffer);
1930 ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
1933 static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
1934 journal_t *journal,
1935 struct problem_context *pctx)
1937 struct ext2_super_block *sb = ctx->fs->super;
1938 int recover = ctx->fs->super->s_feature_incompat &
1939 EXT3_FEATURE_INCOMPAT_RECOVER;
1941 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1942 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
1943 e2fsck_journal_reset_super(ctx, journal->j_superblock,
1944 journal);
1945 journal->j_transaction_sequence = 1;
1946 e2fsck_clear_recover(ctx, recover);
1947 return 0;
1949 return EXT2_ET_CORRUPT_SUPERBLOCK;
1950 } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
1951 return EXT2_ET_CORRUPT_SUPERBLOCK;
1953 return 0;
1956 static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
1957 int reset, int drop)
1959 journal_superblock_t *jsb;
1961 if (drop)
1962 mark_buffer_clean(journal->j_sb_buffer);
1963 else if (!(ctx->options & E2F_OPT_READONLY)) {
1964 jsb = journal->j_superblock;
1965 jsb->s_sequence = htonl(journal->j_transaction_sequence);
1966 if (reset)
1967 jsb->s_start = 0; /* this marks the journal as empty */
1968 mark_buffer_dirty(journal->j_sb_buffer);
1970 brelse(journal->j_sb_buffer);
1972 if (ctx->journal_io) {
1973 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1974 io_channel_close(ctx->journal_io);
1975 ctx->journal_io = 0;
1978 #ifndef USE_INODE_IO
1979 ext2fs_free_mem(&journal->j_inode);
1980 #endif
1981 ext2fs_free_mem(&journal->j_fs_dev);
1982 ext2fs_free_mem(&journal);
1986 * This function makes sure that the superblock fields regarding the
1987 * journal are consistent.
1989 static int e2fsck_check_ext3_journal(e2fsck_t ctx)
1991 struct ext2_super_block *sb = ctx->fs->super;
1992 journal_t *journal;
1993 int recover = ctx->fs->super->s_feature_incompat &
1994 EXT3_FEATURE_INCOMPAT_RECOVER;
1995 struct problem_context pctx;
1996 problem_t problem;
1997 int reset = 0, force_fsck = 0;
1998 int retval;
2000 /* If we don't have any journal features, don't do anything more */
2001 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
2002 !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
2003 uuid_is_null(sb->s_journal_uuid))
2004 return 0;
2006 clear_problem_context(&pctx);
2007 pctx.num = sb->s_journal_inum;
2009 retval = e2fsck_get_journal(ctx, &journal);
2010 if (retval) {
2011 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
2012 (retval == EXT2_ET_BAD_BLOCK_NUM) ||
2013 (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
2014 (retval == EXT2_ET_NO_JOURNAL))
2015 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
2016 return retval;
2019 retval = e2fsck_journal_load(journal);
2020 if (retval) {
2021 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
2022 ((retval == EXT2_ET_UNSUPP_FEATURE) &&
2023 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
2024 &pctx))) ||
2025 ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
2026 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
2027 &pctx))) ||
2028 ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
2029 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
2030 retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
2031 &pctx);
2032 e2fsck_journal_release(ctx, journal, 0, 1);
2033 return retval;
2037 * We want to make the flags consistent here. We will not leave with
2038 * needs_recovery set but has_journal clear. We can't get in a loop
2039 * with -y, -n, or -p, only if a user isn't making up their mind.
2041 no_has_journal:
2042 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
2043 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
2044 pctx.str = "inode";
2045 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
2046 if (recover &&
2047 !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
2048 goto no_has_journal;
2050 * Need a full fsck if we are releasing a
2051 * journal stored on a reserved inode.
2053 force_fsck = recover ||
2054 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
2055 /* Clear all of the journal fields */
2056 sb->s_journal_inum = 0;
2057 sb->s_journal_dev = 0;
2058 memset(sb->s_journal_uuid, 0,
2059 sizeof(sb->s_journal_uuid));
2060 e2fsck_clear_recover(ctx, force_fsck);
2061 } else if (!(ctx->options & E2F_OPT_READONLY)) {
2062 sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2063 ext2fs_mark_super_dirty(ctx->fs);
2067 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
2068 !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
2069 journal->j_superblock->s_start != 0) {
2070 /* Print status information */
2071 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
2072 if (ctx->superblock)
2073 problem = PR_0_JOURNAL_RUN_DEFAULT;
2074 else
2075 problem = PR_0_JOURNAL_RUN;
2076 if (fix_problem(ctx, problem, &pctx)) {
2077 ctx->options |= E2F_OPT_FORCE;
2078 sb->s_feature_incompat |=
2079 EXT3_FEATURE_INCOMPAT_RECOVER;
2080 ext2fs_mark_super_dirty(ctx->fs);
2081 } else if (fix_problem(ctx,
2082 PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
2083 reset = 1;
2084 sb->s_state &= ~EXT2_VALID_FS;
2085 ext2fs_mark_super_dirty(ctx->fs);
2088 * If the user answers no to the above question, we
2089 * ignore the fact that journal apparently has data;
2090 * accidentally replaying over valid data would be far
2091 * worse than skipping a questionable recovery.
2093 * XXX should we abort with a fatal error here? What
2094 * will the ext3 kernel code do if a filesystem with
2095 * !NEEDS_RECOVERY but with a non-zero
2096 * journal->j_superblock->s_start is mounted?
2100 e2fsck_journal_release(ctx, journal, reset, 0);
2101 return retval;
2104 static errcode_t recover_ext3_journal(e2fsck_t ctx)
2106 journal_t *journal;
2107 int retval;
2109 journal_init_revoke_caches();
2110 retval = e2fsck_get_journal(ctx, &journal);
2111 if (retval)
2112 return retval;
2114 retval = e2fsck_journal_load(journal);
2115 if (retval)
2116 goto errout;
2118 retval = journal_init_revoke(journal, 1024);
2119 if (retval)
2120 goto errout;
2122 retval = -journal_recover(journal);
2123 if (retval)
2124 goto errout;
2126 if (journal->j_superblock->s_errno) {
2127 ctx->fs->super->s_state |= EXT2_ERROR_FS;
2128 ext2fs_mark_super_dirty(ctx->fs);
2129 journal->j_superblock->s_errno = 0;
2130 mark_buffer_dirty(journal->j_sb_buffer);
2133 errout:
2134 journal_destroy_revoke(journal);
2135 journal_destroy_revoke_caches();
2136 e2fsck_journal_release(ctx, journal, 1, 0);
2137 return retval;
2140 static int e2fsck_run_ext3_journal(e2fsck_t ctx)
2142 io_manager io_ptr = ctx->fs->io->manager;
2143 int blocksize = ctx->fs->blocksize;
2144 errcode_t retval, recover_retval;
2146 printf(_("%s: recovering journal\n"), ctx->device_name);
2147 if (ctx->options & E2F_OPT_READONLY) {
2148 printf(_("%s: won't do journal recovery while read-only\n"),
2149 ctx->device_name);
2150 return EXT2_ET_FILE_RO;
2153 if (ctx->fs->flags & EXT2_FLAG_DIRTY)
2154 ext2fs_flush(ctx->fs); /* Force out any modifications */
2156 recover_retval = recover_ext3_journal(ctx);
2159 * Reload the filesystem context to get up-to-date data from disk
2160 * because journal recovery will change the filesystem under us.
2162 ext2fs_close(ctx->fs);
2163 retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
2164 ctx->superblock, blocksize, io_ptr,
2165 &ctx->fs);
2167 if (retval) {
2168 bb_error_msg_and_die(_("while trying to re-open %s"),
2169 ctx->device_name);
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_INODE)) {
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_INODE)
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_INODE)) {
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_and_die(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12327 ctx->device_name);
12330 ehandler_operation(_("reading inode and block bitmaps"));
12331 retval = ext2fs_read_bitmaps(fs);
12332 ehandler_operation(0);
12333 if (retval) {
12334 bb_error_msg_and_die(_("while retrying to read bitmaps for %s"),
12335 ctx->device_name);
12339 static void e2fsck_write_bitmaps(e2fsck_t ctx)
12341 ext2_filsys fs = ctx->fs;
12342 errcode_t retval;
12344 if (ext2fs_test_bb_dirty(fs)) {
12345 ehandler_operation(_("writing block bitmaps"));
12346 retval = ext2fs_write_block_bitmap(fs);
12347 ehandler_operation(0);
12348 if (retval) {
12349 bb_error_msg_and_die(_("while retrying to write block bitmaps for %s"),
12350 ctx->device_name);
12354 if (ext2fs_test_ib_dirty(fs)) {
12355 ehandler_operation(_("writing inode bitmaps"));
12356 retval = ext2fs_write_inode_bitmap(fs);
12357 ehandler_operation(0);
12358 if (retval) {
12359 bb_error_msg_and_die(_("while retrying to write inode bitmaps for %s"),
12360 ctx->device_name);
12365 void preenhalt(e2fsck_t ctx)
12367 ext2_filsys fs = ctx->fs;
12369 if (!(ctx->options & E2F_OPT_PREEN))
12370 return;
12371 fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12372 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12373 ctx->device_name);
12374 if (fs != NULL) {
12375 fs->super->s_state |= EXT2_ERROR_FS;
12376 ext2fs_mark_super_dirty(fs);
12377 ext2fs_close(fs);
12379 exit(EXIT_UNCORRECTED);
12382 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12383 struct ext2_inode * inode, const char *proc)
12385 int retval;
12387 retval = ext2fs_read_inode(ctx->fs, ino, inode);
12388 if (retval) {
12389 bb_error_msg_and_die(_("while reading inode %ld in %s"), ino, proc);
12393 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12394 struct ext2_inode * inode, int bufsize,
12395 const char *proc)
12397 int retval;
12399 retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12400 if (retval) {
12401 bb_error_msg_and_die(_("while writing inode %ld in %s"), ino, proc);
12405 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12406 struct ext2_inode * inode, const char *proc)
12408 int retval;
12410 retval = ext2fs_write_inode(ctx->fs, ino, inode);
12411 if (retval) {
12412 bb_error_msg_and_die(_("while writing inode %ld in %s"), ino, proc);
12416 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12417 io_manager manager)
12419 struct ext2_super_block *sb;
12420 io_channel io = NULL;
12421 void *buf = NULL;
12422 int blocksize;
12423 blk_t superblock, ret_sb = 8193;
12425 if (fs && fs->super) {
12426 ret_sb = (fs->super->s_blocks_per_group +
12427 fs->super->s_first_data_block);
12428 if (ctx) {
12429 ctx->superblock = ret_sb;
12430 ctx->blocksize = fs->blocksize;
12432 return ret_sb;
12435 if (ctx) {
12436 if (ctx->blocksize) {
12437 ret_sb = ctx->blocksize * 8;
12438 if (ctx->blocksize == 1024)
12439 ret_sb++;
12440 ctx->superblock = ret_sb;
12441 return ret_sb;
12443 ctx->superblock = ret_sb;
12444 ctx->blocksize = 1024;
12447 if (!name || !manager)
12448 goto cleanup;
12450 if (manager->open(name, 0, &io) != 0)
12451 goto cleanup;
12453 if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12454 goto cleanup;
12455 sb = (struct ext2_super_block *) buf;
12457 for (blocksize = EXT2_MIN_BLOCK_SIZE;
12458 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
12459 superblock = blocksize*8;
12460 if (blocksize == 1024)
12461 superblock++;
12462 io_channel_set_blksize(io, blocksize);
12463 if (io_channel_read_blk(io, superblock,
12464 -SUPERBLOCK_SIZE, buf))
12465 continue;
12466 #if BB_BIG_ENDIAN
12467 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12468 ext2fs_swap_super(sb);
12469 #endif
12470 if (sb->s_magic == EXT2_SUPER_MAGIC) {
12471 ret_sb = superblock;
12472 if (ctx) {
12473 ctx->superblock = superblock;
12474 ctx->blocksize = blocksize;
12476 break;
12480 cleanup:
12481 if (io)
12482 io_channel_close(io);
12483 ext2fs_free_mem(&buf);
12484 return ret_sb;
12489 * This function runs through the e2fsck passes and calls them all,
12490 * returning restart, abort, or cancel as necessary...
12492 typedef void (*pass_t)(e2fsck_t ctx);
12494 static const pass_t e2fsck_passes[] = {
12495 e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12496 e2fsck_pass5, 0 };
12498 #define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12500 static int e2fsck_run(e2fsck_t ctx)
12502 int i;
12503 pass_t e2fsck_pass;
12505 if (setjmp(ctx->abort_loc)) {
12506 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12507 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12509 ctx->flags |= E2F_FLAG_SETJMP_OK;
12511 for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12512 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12513 break;
12514 e2fsck_pass(ctx);
12515 if (ctx->progress)
12516 (void) (ctx->progress)(ctx, 0, 0, 0);
12518 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12520 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12521 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12522 return 0;
12527 * unix.c - The unix-specific code for e2fsck
12531 /* Command line options */
12532 static int swapfs;
12533 #ifdef ENABLE_SWAPFS
12534 static int normalize_swapfs;
12535 #endif
12536 static int cflag; /* check disk */
12537 static int show_version_only;
12538 static int verbose;
12540 #define P_E2(singular, plural, n) n, ((n) == 1 ? singular : plural)
12542 static void show_stats(e2fsck_t ctx)
12544 ext2_filsys fs = ctx->fs;
12545 int inodes, inodes_used, blocks, blocks_used;
12546 int dir_links;
12547 int num_files, num_links;
12548 int frag_percent;
12550 dir_links = 2 * ctx->fs_directory_count - 1;
12551 num_files = ctx->fs_total_count - dir_links;
12552 num_links = ctx->fs_links_count - dir_links;
12553 inodes = fs->super->s_inodes_count;
12554 inodes_used = (fs->super->s_inodes_count -
12555 fs->super->s_free_inodes_count);
12556 blocks = fs->super->s_blocks_count;
12557 blocks_used = (fs->super->s_blocks_count -
12558 fs->super->s_free_blocks_count);
12560 frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12561 frag_percent = (frag_percent + 5) / 10;
12563 if (!verbose) {
12564 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12565 ctx->device_name, inodes_used, inodes,
12566 frag_percent / 10, frag_percent % 10,
12567 blocks_used, blocks);
12568 return;
12570 printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12571 100 * inodes_used / inodes);
12572 printf("%8d non-contiguous inode%s (%0d.%d%%)\n",
12573 P_E2("", "s", ctx->fs_fragmented),
12574 frag_percent / 10, frag_percent % 10);
12575 printf(_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12576 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12577 printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12578 (int) ((long long) 100 * blocks_used / blocks));
12579 printf("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12580 printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12581 printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12582 printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12583 printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12584 printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12585 printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12586 printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12587 printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12588 printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12589 printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12592 static void check_mount(e2fsck_t ctx)
12594 errcode_t retval;
12595 int cont;
12597 retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12598 &ctx->mount_flags);
12599 if (retval) {
12600 bb_error_msg(_("while determining whether %s is mounted"),
12601 ctx->filesystem_name);
12602 return;
12606 * If the filesystem isn't mounted, or it's the root filesystem
12607 * and it's mounted read-only, then everything's fine.
12609 if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12610 ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12611 (ctx->mount_flags & EXT2_MF_READONLY)))
12612 return;
12614 if (ctx->options & E2F_OPT_READONLY) {
12615 printf(_("Warning! %s is mounted.\n"), ctx->filesystem_name);
12616 return;
12619 printf(_("%s is mounted. "), ctx->filesystem_name);
12620 if (!ctx->interactive)
12621 bb_error_msg_and_die(_("can't continue, aborting"));
12622 printf(_("\n\n\007\007\007\007WARNING!!! "
12623 "Running e2fsck on a mounted filesystem may cause\n"
12624 "SEVERE filesystem damage.\007\007\007\n\n"));
12625 cont = ask_yn(_("Do you really want to continue"), -1);
12626 if (!cont) {
12627 printf(_("check aborted.\n"));
12628 exit(0);
12632 static int is_on_batt(void)
12634 FILE *f;
12635 DIR *d;
12636 char tmp[80], tmp2[80], fname[80];
12637 unsigned int acflag;
12638 struct dirent* de;
12640 f = fopen_for_read("/proc/apm");
12641 if (f) {
12642 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12643 acflag = 1;
12644 fclose(f);
12645 return (acflag != 1);
12647 d = opendir("/proc/acpi/ac_adapter");
12648 if (d) {
12649 while ((de=readdir(d)) != NULL) {
12650 if (!strncmp(".", de->d_name, 1))
12651 continue;
12652 snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12653 de->d_name);
12654 f = fopen_for_read(fname);
12655 if (!f)
12656 continue;
12657 if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12658 tmp[0] = 0;
12659 fclose(f);
12660 if (strncmp(tmp, "off-line", 8) == 0) {
12661 closedir(d);
12662 return 1;
12665 closedir(d);
12667 return 0;
12671 * This routine checks to see if a filesystem can be skipped; if so,
12672 * it will exit with EXIT_OK. Under some conditions it will print a
12673 * message explaining why a check is being forced.
12675 static void check_if_skip(e2fsck_t ctx)
12677 ext2_filsys fs = ctx->fs;
12678 const char *reason = NULL;
12679 unsigned int reason_arg = 0;
12680 long next_check;
12681 int batt = is_on_batt();
12682 time_t now = time(NULL);
12684 if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12685 return;
12687 if ((fs->super->s_state & EXT2_ERROR_FS) ||
12688 !ext2fs_test_valid(fs))
12689 reason = _(" contains a file system with errors");
12690 else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12691 reason = _(" was not cleanly unmounted");
12692 else if ((fs->super->s_max_mnt_count > 0) &&
12693 (fs->super->s_mnt_count >=
12694 (unsigned) fs->super->s_max_mnt_count)) {
12695 reason = _(" has been mounted %u times without being checked");
12696 reason_arg = fs->super->s_mnt_count;
12697 if (batt && (fs->super->s_mnt_count <
12698 (unsigned) fs->super->s_max_mnt_count*2))
12699 reason = 0;
12700 } else if (!(ctx->options & E2F_OPT_PREEN) &&
12701 fs->super->s_checkinterval &&
12702 ((now - fs->super->s_lastcheck) >=
12703 fs->super->s_checkinterval)) {
12704 reason = _(" has gone %u days without being checked");
12705 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12706 if (batt && ((now - fs->super->s_lastcheck) <
12707 fs->super->s_checkinterval*2))
12708 reason = 0;
12710 if (reason) {
12711 fputs(ctx->device_name, stdout);
12712 printf(reason, reason_arg);
12713 fputs(_(", check forced.\n"), stdout);
12714 return;
12716 printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12717 fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12718 fs->super->s_inodes_count,
12719 fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12720 fs->super->s_blocks_count);
12721 next_check = 100000;
12722 if (fs->super->s_max_mnt_count > 0) {
12723 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12724 if (next_check <= 0)
12725 next_check = 1;
12727 if (fs->super->s_checkinterval &&
12728 ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12729 next_check = 1;
12730 if (next_check <= 5) {
12731 if (next_check == 1)
12732 fputs(_(" (check after next mount)"), stdout);
12733 else
12734 printf(_(" (check in %ld mounts)"), next_check);
12736 bb_putchar('\n');
12737 ext2fs_close(fs);
12738 ctx->fs = NULL;
12739 e2fsck_free_context(ctx);
12740 exit(EXIT_OK);
12744 * For completion notice
12746 struct percent_tbl {
12747 int max_pass;
12748 int table[32];
12750 static const struct percent_tbl e2fsck_tbl = {
12751 5, { 0, 70, 90, 92, 95, 100 }
12754 static char bar[128], spaces[128];
12756 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12757 int max)
12759 float percent;
12761 if (pass <= 0)
12762 return 0.0;
12763 if (pass > tbl->max_pass || max == 0)
12764 return 100.0;
12765 percent = ((float) curr) / ((float) max);
12766 return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12767 + tbl->table[pass-1]);
12770 void e2fsck_clear_progbar(e2fsck_t ctx)
12772 if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12773 return;
12775 printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12776 ctx->stop_meta);
12777 fflush(stdout);
12778 ctx->flags &= ~E2F_FLAG_PROG_BAR;
12781 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12782 unsigned int dpynum)
12784 static const char spinner[] = "\\|/-";
12785 int i;
12786 unsigned int tick;
12787 struct timeval tv;
12788 int dpywidth;
12789 int fixed_percent;
12791 if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12792 return 0;
12795 * Calculate the new progress position. If the
12796 * percentage hasn't changed, then we skip out right
12797 * away.
12799 fixed_percent = (int) ((10 * percent) + 0.5);
12800 if (ctx->progress_last_percent == fixed_percent)
12801 return 0;
12802 ctx->progress_last_percent = fixed_percent;
12805 * If we've already updated the spinner once within
12806 * the last 1/8th of a second, no point doing it
12807 * again.
12809 gettimeofday(&tv, NULL);
12810 tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12811 if ((tick == ctx->progress_last_time) &&
12812 (fixed_percent != 0) && (fixed_percent != 1000))
12813 return 0;
12814 ctx->progress_last_time = tick;
12817 * Advance the spinner, and note that the progress bar
12818 * will be on the screen
12820 ctx->progress_pos = (ctx->progress_pos+1) & 3;
12821 ctx->flags |= E2F_FLAG_PROG_BAR;
12823 dpywidth = 66 - strlen(label);
12824 dpywidth = 8 * (dpywidth / 8);
12825 if (dpynum)
12826 dpywidth -= 8;
12828 i = ((percent * dpywidth) + 50) / 100;
12829 printf("%s%s: |%s%s", ctx->start_meta, label,
12830 bar + (sizeof(bar) - (i+1)),
12831 spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12832 if (fixed_percent == 1000)
12833 bb_putchar('|');
12834 else
12835 bb_putchar(spinner[ctx->progress_pos & 3]);
12836 printf(" %4.1f%% ", percent);
12837 if (dpynum)
12838 printf("%u\r", dpynum);
12839 else
12840 fputs(" \r", stdout);
12841 fputs(ctx->stop_meta, stdout);
12843 if (fixed_percent == 1000)
12844 e2fsck_clear_progbar(ctx);
12845 fflush(stdout);
12847 return 0;
12850 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12851 unsigned long cur, unsigned long max)
12853 char buf[80];
12854 float percent;
12856 if (pass == 0)
12857 return 0;
12859 if (ctx->progress_fd) {
12860 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
12861 xwrite_str(ctx->progress_fd, buf);
12862 } else {
12863 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12864 e2fsck_simple_progress(ctx, ctx->device_name,
12865 percent, 0);
12867 return 0;
12870 static void reserve_stdio_fds(void)
12872 int fd;
12874 while (1) {
12875 fd = open(bb_dev_null, O_RDWR);
12876 if (fd > 2)
12877 break;
12878 if (fd < 0) {
12879 fprintf(stderr, _("ERROR: Cannot open "
12880 "/dev/null (%s)\n"),
12881 strerror(errno));
12882 break;
12885 close(fd);
12888 static void signal_progress_on(int sig FSCK_ATTR((unused)))
12890 e2fsck_t ctx = e2fsck_global_ctx;
12892 if (!ctx)
12893 return;
12895 ctx->progress = e2fsck_update_progress;
12896 ctx->progress_fd = 0;
12899 static void signal_progress_off(int sig FSCK_ATTR((unused)))
12901 e2fsck_t ctx = e2fsck_global_ctx;
12903 if (!ctx)
12904 return;
12906 e2fsck_clear_progbar(ctx);
12907 ctx->progress = 0;
12910 static void signal_cancel(int sig FSCK_ATTR((unused)))
12912 e2fsck_t ctx = e2fsck_global_ctx;
12914 if (!ctx)
12915 exit(FSCK_CANCELED);
12917 ctx->flags |= E2F_FLAG_CANCEL;
12920 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12922 char *buf, *token, *next, *p, *arg;
12923 int ea_ver;
12924 int extended_usage = 0;
12926 buf = string_copy(opts, 0);
12927 for (token = buf; token && *token; token = next) {
12928 p = strchr(token, ',');
12929 next = 0;
12930 if (p) {
12931 *p = 0;
12932 next = p+1;
12934 arg = strchr(token, '=');
12935 if (arg) {
12936 *arg = 0;
12937 arg++;
12939 if (strcmp(token, "ea_ver") == 0) {
12940 if (!arg) {
12941 extended_usage++;
12942 continue;
12944 ea_ver = strtoul(arg, &p, 0);
12945 if (*p ||
12946 ((ea_ver != 1) && (ea_ver != 2))) {
12947 fprintf(stderr,
12948 _("Invalid EA version.\n"));
12949 extended_usage++;
12950 continue;
12952 ctx->ext_attr_ver = ea_ver;
12953 } else {
12954 fprintf(stderr, _("Unknown extended option: %s\n"),
12955 token);
12956 extended_usage++;
12959 if (extended_usage) {
12960 bb_error_msg_and_die(
12961 "Extended options are separated by commas, "
12962 "and may take an argument which\n"
12963 "is set off by an equals ('=') sign. "
12964 "Valid extended options are:\n"
12965 "\tea_ver=<ea_version (1 or 2)>\n\n");
12970 static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
12972 int flush = 0;
12973 int c, fd;
12974 e2fsck_t ctx;
12975 errcode_t retval;
12976 struct sigaction sa;
12977 char *extended_opts = NULL;
12979 retval = e2fsck_allocate_context(&ctx);
12980 if (retval)
12981 return retval;
12983 *ret_ctx = ctx;
12985 setvbuf(stdout, NULL, _IONBF, BUFSIZ);
12986 setvbuf(stderr, NULL, _IONBF, BUFSIZ);
12987 if (isatty(0) && isatty(1)) {
12988 ctx->interactive = 1;
12989 } else {
12990 ctx->start_meta[0] = '\001';
12991 ctx->stop_meta[0] = '\002';
12993 memset(bar, '=', sizeof(bar)-1);
12994 memset(spaces, ' ', sizeof(spaces)-1);
12996 if (argc && *argv)
12997 ctx->program_name = *argv;
12998 else
12999 ctx->program_name = "e2fsck";
13000 while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
13001 switch (c) {
13002 case 'C':
13003 ctx->progress = e2fsck_update_progress;
13004 ctx->progress_fd = atoi(optarg);
13005 if (!ctx->progress_fd)
13006 break;
13007 /* Validate the file descriptor to avoid disasters */
13008 fd = dup(ctx->progress_fd);
13009 if (fd < 0) {
13010 fprintf(stderr,
13011 _("Error validating file descriptor %d: %s\n"),
13012 ctx->progress_fd,
13013 error_message(errno));
13014 bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13015 } else
13016 close(fd);
13017 break;
13018 case 'D':
13019 ctx->options |= E2F_OPT_COMPRESS_DIRS;
13020 break;
13021 case 'E':
13022 extended_opts = optarg;
13023 break;
13024 case 'p':
13025 case 'a':
13026 if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13027 conflict_opt:
13028 bb_error_msg_and_die(_("only one the options -p/-a, -n or -y may be specified"));
13030 ctx->options |= E2F_OPT_PREEN;
13031 break;
13032 case 'n':
13033 if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13034 goto conflict_opt;
13035 ctx->options |= E2F_OPT_NO;
13036 break;
13037 case 'y':
13038 if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13039 goto conflict_opt;
13040 ctx->options |= E2F_OPT_YES;
13041 break;
13042 case 't':
13043 /* FIXME - This needs to go away in a future path - will change binary */
13044 fprintf(stderr, _("The -t option is not "
13045 "supported on this version of e2fsck.\n"));
13046 break;
13047 case 'c':
13048 if (cflag++)
13049 ctx->options |= E2F_OPT_WRITECHECK;
13050 ctx->options |= E2F_OPT_CHECKBLOCKS;
13051 break;
13052 case 'r':
13053 /* What we do by default, anyway! */
13054 break;
13055 case 'b':
13056 ctx->use_superblock = atoi(optarg);
13057 ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13058 break;
13059 case 'B':
13060 ctx->blocksize = atoi(optarg);
13061 break;
13062 case 'I':
13063 ctx->inode_buffer_blocks = atoi(optarg);
13064 break;
13065 case 'j':
13066 ctx->journal_name = string_copy(optarg, 0);
13067 break;
13068 case 'P':
13069 ctx->process_inode_size = atoi(optarg);
13070 break;
13071 case 'd':
13072 ctx->options |= E2F_OPT_DEBUG;
13073 break;
13074 case 'f':
13075 ctx->options |= E2F_OPT_FORCE;
13076 break;
13077 case 'F':
13078 flush = 1;
13079 break;
13080 case 'v':
13081 verbose = 1;
13082 break;
13083 case 'V':
13084 show_version_only = 1;
13085 break;
13086 case 'N':
13087 ctx->device_name = optarg;
13088 break;
13089 #ifdef ENABLE_SWAPFS
13090 case 's':
13091 normalize_swapfs = 1;
13092 case 'S':
13093 swapfs = 1;
13094 break;
13095 #else
13096 case 's':
13097 case 'S':
13098 fprintf(stderr, _("Byte-swapping filesystems "
13099 "not compiled in this version "
13100 "of e2fsck\n"));
13101 exit(1);
13102 #endif
13103 default:
13104 bb_show_usage();
13106 if (show_version_only)
13107 return 0;
13108 if (optind != argc - 1)
13109 bb_show_usage();
13110 if ((ctx->options & E2F_OPT_NO) &&
13111 !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13112 ctx->options |= E2F_OPT_READONLY;
13113 ctx->io_options = strchr(argv[optind], '?');
13114 if (ctx->io_options)
13115 *ctx->io_options++ = 0;
13116 ctx->filesystem_name = argv[optind];
13117 if (resolve_mount_spec(&ctx->filesystem_name) < 0 ||
13118 !ctx->filesystem_name) {
13119 bb_error_msg_and_die(_("Unable to resolve '%s'"), argv[optind]);
13121 if (extended_opts)
13122 parse_extended_opts(ctx, extended_opts);
13124 if (flush) {
13125 fd = open(ctx->filesystem_name, O_RDONLY, 0);
13126 if (fd < 0) {
13127 bb_error_msg_and_die(_("while opening %s for flushing"),
13128 ctx->filesystem_name);
13130 if ((retval = ext2fs_sync_device(fd, 1))) {
13131 bb_error_msg_and_die(_("while trying to flush %s"),
13132 ctx->filesystem_name);
13134 close(fd);
13136 #ifdef ENABLE_SWAPFS
13137 if (swapfs && cflag) {
13138 fprintf(stderr, _("Incompatible options not "
13139 "allowed when byte-swapping.\n"));
13140 exit(EXIT_USAGE);
13142 #endif
13144 * Set up signal action
13146 memset(&sa, 0, sizeof(struct sigaction));
13147 sa.sa_handler = signal_cancel;
13148 sigaction(SIGINT, &sa, 0);
13149 sigaction(SIGTERM, &sa, 0);
13150 #ifdef SA_RESTART
13151 sa.sa_flags = SA_RESTART;
13152 #endif
13153 e2fsck_global_ctx = ctx;
13154 sa.sa_handler = signal_progress_on;
13155 sigaction(SIGUSR1, &sa, 0);
13156 sa.sa_handler = signal_progress_off;
13157 sigaction(SIGUSR2, &sa, 0);
13159 /* Update our PATH to include /sbin if we need to run badblocks */
13160 if (cflag)
13161 e2fs_set_sbin_path();
13162 return 0;
13165 static const char my_ver_string[] = E2FSPROGS_VERSION;
13166 static const char my_ver_date[] = E2FSPROGS_DATE;
13168 int e2fsck_main (int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13169 int e2fsck_main (int argc, char **argv)
13171 errcode_t retval;
13172 int exit_value = EXIT_OK;
13173 ext2_filsys fs = 0;
13174 io_manager io_ptr;
13175 struct ext2_super_block *sb;
13176 const char *lib_ver_date;
13177 int my_ver, lib_ver;
13178 e2fsck_t ctx;
13179 struct problem_context pctx;
13180 int flags, run_result;
13182 clear_problem_context(&pctx);
13184 my_ver = ext2fs_parse_version_string(my_ver_string);
13185 lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13186 if (my_ver > lib_ver) {
13187 fprintf( stderr, _("Error: ext2fs library version "
13188 "out of date!\n"));
13189 show_version_only++;
13192 retval = PRS(argc, argv, &ctx);
13193 if (retval) {
13194 bb_error_msg(_("while trying to initialize program"));
13195 exit(EXIT_ERROR);
13197 reserve_stdio_fds();
13199 if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13200 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13201 my_ver_date);
13203 if (show_version_only) {
13204 fprintf(stderr, _("\tUsing %s, %s\n"),
13205 error_message(EXT2_ET_BASE), lib_ver_date);
13206 exit(EXIT_OK);
13209 check_mount(ctx);
13211 if (!(ctx->options & E2F_OPT_PREEN) &&
13212 !(ctx->options & E2F_OPT_NO) &&
13213 !(ctx->options & E2F_OPT_YES)) {
13214 if (!ctx->interactive)
13215 bb_error_msg_and_die(_("need terminal for interactive repairs"));
13217 ctx->superblock = ctx->use_superblock;
13218 restart:
13219 #ifdef CONFIG_TESTIO_DEBUG
13220 io_ptr = test_io_manager;
13221 test_io_backing_manager = unix_io_manager;
13222 #else
13223 io_ptr = unix_io_manager;
13224 #endif
13225 flags = 0;
13226 if ((ctx->options & E2F_OPT_READONLY) == 0)
13227 flags |= EXT2_FLAG_RW;
13229 if (ctx->superblock && ctx->blocksize) {
13230 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13231 flags, ctx->superblock, ctx->blocksize,
13232 io_ptr, &fs);
13233 } else if (ctx->superblock) {
13234 int blocksize;
13235 for (blocksize = EXT2_MIN_BLOCK_SIZE;
13236 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13237 retval = ext2fs_open2(ctx->filesystem_name,
13238 ctx->io_options, flags,
13239 ctx->superblock, blocksize,
13240 io_ptr, &fs);
13241 if (!retval)
13242 break;
13244 } else
13245 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13246 flags, 0, 0, io_ptr, &fs);
13247 if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13248 !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13249 ((retval == EXT2_ET_BAD_MAGIC) ||
13250 ((retval == 0) && ext2fs_check_desc(fs)))) {
13251 if (!fs || (fs->group_desc_count > 1)) {
13252 printf(_("%s trying backup blocks...\n"),
13253 retval ? _("Couldn't find ext2 superblock,") :
13254 _("Group descriptors look bad..."));
13255 get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13256 if (fs)
13257 ext2fs_close(fs);
13258 goto restart;
13261 if (retval) {
13262 bb_error_msg(_("while trying to open %s"),
13263 ctx->filesystem_name);
13264 if (retval == EXT2_ET_REV_TOO_HIGH) {
13265 printf(_("The filesystem revision is apparently "
13266 "too high for this version of e2fsck.\n"
13267 "(Or the filesystem superblock "
13268 "is corrupt)\n\n"));
13269 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13270 } else if (retval == EXT2_ET_SHORT_READ)
13271 printf(_("Could this be a zero-length partition?\n"));
13272 else if ((retval == EPERM) || (retval == EACCES))
13273 printf(_("You must have %s access to the "
13274 "filesystem or be root\n"),
13275 (ctx->options & E2F_OPT_READONLY) ?
13276 "r/o" : "r/w");
13277 else if (retval == ENXIO)
13278 printf(_("Possibly non-existent or swap device?\n"));
13279 #ifdef EROFS
13280 else if (retval == EROFS)
13281 printf(_("Disk write-protected; use the -n option "
13282 "to do a read-only\n"
13283 "check of the device.\n"));
13284 #endif
13285 else
13286 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13287 bb_error_msg_and_die(0);
13289 ctx->fs = fs;
13290 fs->priv_data = ctx;
13291 sb = fs->super;
13292 if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13293 bb_error_msg(_("while trying to open %s"),
13294 ctx->filesystem_name);
13295 get_newer:
13296 bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13300 * Set the device name, which is used whenever we print error
13301 * or informational messages to the user.
13303 if (ctx->device_name == 0 &&
13304 (sb->s_volume_name[0] != 0)) {
13305 ctx->device_name = string_copy(sb->s_volume_name,
13306 sizeof(sb->s_volume_name));
13308 if (ctx->device_name == 0)
13309 ctx->device_name = ctx->filesystem_name;
13312 * Make sure the ext3 superblock fields are consistent.
13314 retval = e2fsck_check_ext3_journal(ctx);
13315 if (retval) {
13316 bb_error_msg_and_die(_("while checking ext3 journal for %s"),
13317 ctx->device_name);
13321 * Check to see if we need to do ext3-style recovery. If so,
13322 * do it, and then restart the fsck.
13324 if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13325 if (ctx->options & E2F_OPT_READONLY) {
13326 printf(_("Warning: skipping journal recovery "
13327 "because doing a read-only filesystem "
13328 "check.\n"));
13329 io_channel_flush(ctx->fs->io);
13330 } else {
13331 if (ctx->flags & E2F_FLAG_RESTARTED) {
13333 * Whoops, we attempted to run the
13334 * journal twice. This should never
13335 * happen, unless the hardware or
13336 * device driver is being bogus.
13338 bb_error_msg_and_die(_("can't set superblock flags on %s"), ctx->device_name);
13340 retval = e2fsck_run_ext3_journal(ctx);
13341 if (retval) {
13342 bb_error_msg_and_die(_("while recovering ext3 journal of %s"),
13343 ctx->device_name);
13345 ext2fs_close(ctx->fs);
13346 ctx->fs = 0;
13347 ctx->flags |= E2F_FLAG_RESTARTED;
13348 goto restart;
13353 * Check for compatibility with the feature sets. We need to
13354 * be more stringent than ext2fs_open().
13356 if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13357 (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13358 bb_error_msg("(%s)", ctx->device_name);
13359 goto get_newer;
13361 if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13362 bb_error_msg("(%s)", ctx->device_name);
13363 goto get_newer;
13365 #ifdef ENABLE_COMPRESSION
13366 /* FIXME - do we support this at all? */
13367 if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
13368 bb_error_msg(_("warning: compression support is experimental"));
13369 #endif
13370 #ifndef ENABLE_HTREE
13371 if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13372 bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13373 "but filesystem %s has HTREE directories."),
13374 ctx->device_name);
13375 goto get_newer;
13377 #endif
13380 * If the user specified a specific superblock, presumably the
13381 * master superblock has been trashed. So we mark the
13382 * superblock as dirty, so it can be written out.
13384 if (ctx->superblock &&
13385 !(ctx->options & E2F_OPT_READONLY))
13386 ext2fs_mark_super_dirty(fs);
13389 * We only update the master superblock because (a) paranoia;
13390 * we don't want to corrupt the backup superblocks, and (b) we
13391 * don't need to update the mount count and last checked
13392 * fields in the backup superblock (the kernel doesn't
13393 * update the backup superblocks anyway).
13395 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13397 ehandler_init(fs->io);
13399 if (ctx->superblock)
13400 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13401 ext2fs_mark_valid(fs);
13402 check_super_block(ctx);
13403 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13404 bb_error_msg_and_die(0);
13405 check_if_skip(ctx);
13406 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13407 bb_error_msg_and_die(0);
13408 #ifdef ENABLE_SWAPFS
13410 #ifdef WORDS_BIGENDIAN
13411 #define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13412 #else
13413 #define NATIVE_FLAG 0
13414 #endif
13417 if (normalize_swapfs) {
13418 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13419 fprintf(stderr, _("%s: Filesystem byte order "
13420 "already normalized.\n"), ctx->device_name);
13421 bb_error_msg_and_die(0);
13424 if (swapfs) {
13425 swap_filesys(ctx);
13426 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13427 bb_error_msg_and_die(0);
13429 #endif
13432 * Mark the system as valid, 'til proven otherwise
13434 ext2fs_mark_valid(fs);
13436 retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13437 if (retval) {
13438 bb_error_msg(_("while reading bad blocks inode"));
13439 preenhalt(ctx);
13440 printf(_("This doesn't bode well,"
13441 " but we'll try to go on...\n"));
13444 run_result = e2fsck_run(ctx);
13445 e2fsck_clear_progbar(ctx);
13446 if (run_result == E2F_FLAG_RESTART) {
13447 printf(_("Restarting e2fsck from the beginning...\n"));
13448 retval = e2fsck_reset_context(ctx);
13449 if (retval) {
13450 bb_error_msg_and_die(_("while resetting context"));
13452 ext2fs_close(fs);
13453 goto restart;
13455 if (run_result & E2F_FLAG_CANCEL) {
13456 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13457 ctx->device_name : ctx->filesystem_name);
13458 exit_value |= FSCK_CANCELED;
13460 if (run_result & E2F_FLAG_ABORT)
13461 bb_error_msg_and_die(_("aborted"));
13463 /* Cleanup */
13464 if (ext2fs_test_changed(fs)) {
13465 exit_value |= EXIT_NONDESTRUCT;
13466 if (!(ctx->options & E2F_OPT_PREEN))
13467 printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13468 ctx->device_name);
13469 if (ctx->mount_flags & EXT2_MF_ISROOT) {
13470 printf(_("%s: ***** REBOOT LINUX *****\n"),
13471 ctx->device_name);
13472 exit_value |= EXIT_DESTRUCT;
13475 if (!ext2fs_test_valid(fs)) {
13476 printf(_("\n%s: ********** WARNING: Filesystem still has "
13477 "errors **********\n\n"), ctx->device_name);
13478 exit_value |= EXIT_UNCORRECTED;
13479 exit_value &= ~EXIT_NONDESTRUCT;
13481 if (exit_value & FSCK_CANCELED)
13482 exit_value &= ~EXIT_NONDESTRUCT;
13483 else {
13484 show_stats(ctx);
13485 if (!(ctx->options & E2F_OPT_READONLY)) {
13486 if (ext2fs_test_valid(fs)) {
13487 if (!(sb->s_state & EXT2_VALID_FS))
13488 exit_value |= EXIT_NONDESTRUCT;
13489 sb->s_state = EXT2_VALID_FS;
13490 } else
13491 sb->s_state &= ~EXT2_VALID_FS;
13492 sb->s_mnt_count = 0;
13493 sb->s_lastcheck = time(NULL);
13494 ext2fs_mark_super_dirty(fs);
13498 e2fsck_write_bitmaps(ctx);
13500 ext2fs_close(fs);
13501 ctx->fs = NULL;
13502 if (ENABLE_FEATURE_CLEAN_UP) {
13503 free(ctx->filesystem_name);
13504 free(ctx->journal_name);
13506 e2fsck_free_context(ctx);
13508 return exit_value;