aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--e2fsprogs/e2fsbb.h2
-rw-r--r--e2fsprogs/e2fsck.c1635
2 files changed, 459 insertions, 1178 deletions
diff --git a/e2fsprogs/e2fsbb.h b/e2fsprogs/e2fsbb.h
index 45079df81..7e4d1ab48 100644
--- a/e2fsprogs/e2fsbb.h
+++ b/e2fsprogs/e2fsbb.h
@@ -29,7 +29,6 @@ typedef long errcode_t;
29/* NLS crap */ 29/* NLS crap */
30#define _(x) x 30#define _(x) x
31#define N_(x) x 31#define N_(x) x
32#define P_(singular, plural, n) ((n) == 1 ? (singular) : (plural))
33 32
34/* misc crap */ 33/* misc crap */
35#define fatal_error(err, msg) bb_error_msg_and_die(msg) 34#define fatal_error(err, msg) bb_error_msg_and_die(msg)
@@ -38,7 +37,6 @@ typedef long errcode_t;
38 37
39/* header defines */ 38/* header defines */
40#define ENABLE_HTREE 1 39#define ENABLE_HTREE 1
41#define HAVE_DIRENT_H 1
42#define HAVE_ERRNO_H 1 40#define HAVE_ERRNO_H 1
43#define HAVE_EXT2_IOCTLS 1 41#define HAVE_EXT2_IOCTLS 1
44#define HAVE_GETOPT_H 1 42#define HAVE_GETOPT_H 1
diff --git a/e2fsprogs/e2fsck.c b/e2fsprogs/e2fsck.c
index 74bc9f7b8..3af03f433 100644
--- a/e2fsprogs/e2fsck.c
+++ b/e2fsprogs/e2fsck.c
@@ -1,9 +1,35 @@
1/* 1/*
2 * e2fsck 2 * e2fsck
3 * 3 *
4 * Copyright (C) 1993, 1994 Theodore Ts'o. This file may be 4 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
5 * This file may be
5 * redistributed under the terms of the GNU Public License. 6 * redistributed under the terms of the GNU Public License.
6 * 7 *
8 *
9 * Dictionary Abstract Data Type
10 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
11 * Free Software License:
12 * All rights are reserved by the author, with the following exceptions:
13 * Permission is granted to freely reproduce and distribute this software,
14 * possibly in exchange for a fee, provided that this copyright notice appears
15 * intact. Permission is also granted to adapt this software to produce
16 * derivative works, as long as the modified versions carry this copyright
17 * notice and additional notices stating that the work has been modified.
18 * This source code may be translated into executable form and incorporated
19 * into proprietary software; there is no requirement for such software to
20 * contain a copyright notice related to this source.
21 *
22 * linux/fs/recovery and linux/fs/revoke
23 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
24 *
25 * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
26 *
27 * This file is part of the Linux kernel and is made available under
28 * the terms of the GNU General Public License, version 2, or at your
29 * option, any later version, incorporated herein by reference.
30 *
31 * Journal recovery routines for the generic filesystem journaling code;
32 * part of the ext2fs journaling system.
7 */ 33 */
8 34
9#ifndef _GNU_SOURCE 35#ifndef _GNU_SOURCE
@@ -172,16 +198,17 @@ struct resource_track {
172#define E2F_PASS_5 5 198#define E2F_PASS_5 5
173#define E2F_PASS_1B 6 199#define E2F_PASS_1B 6
174 200
175/*
176 * Define the extended attribute refcount structure
177 */
178typedef struct ea_refcount *ext2_refcount_t;
179 201
180/* 202/*
181 * This is the global e2fsck structure. 203 * This is the global e2fsck structure.
182 */ 204 */
183typedef struct e2fsck_struct *e2fsck_t; 205typedef struct e2fsck_struct *e2fsck_t;
184 206
207/*
208 * Define the extended attribute refcount structure
209 */
210typedef struct ea_refcount *ext2_refcount_t;
211
185struct e2fsck_struct { 212struct e2fsck_struct {
186 ext2_filsys fs; 213 ext2_filsys fs;
187 const char *program_name; 214 const char *program_name;
@@ -335,64 +362,10 @@ typedef struct region_struct *region_t;
335 * Procedure declarations 362 * Procedure declarations
336 */ 363 */
337 364
338static void e2fsck_pass1(e2fsck_t ctx);
339static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf); 365static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
340static void e2fsck_pass2(e2fsck_t ctx);
341static void e2fsck_pass3(e2fsck_t ctx);
342static void e2fsck_pass4(e2fsck_t ctx);
343static void e2fsck_pass5(e2fsck_t ctx);
344
345/* e2fsck.c */
346static errcode_t e2fsck_allocate_context(e2fsck_t *ret);
347static errcode_t e2fsck_reset_context(e2fsck_t ctx);
348static void e2fsck_free_context(e2fsck_t ctx);
349static int e2fsck_run(e2fsck_t ctx);
350
351
352/* badblock.c */
353static void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file,
354 int replace_bad_blocks);
355
356/* dirinfo.c */
357static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent);
358static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino);
359static void e2fsck_free_dir_info(e2fsck_t ctx);
360static int e2fsck_get_num_dirinfo(e2fsck_t ctx);
361static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control);
362
363/* dx_dirinfo.c */
364static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks);
365static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino);
366static void e2fsck_free_dx_dir_info(e2fsck_t ctx);
367static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control);
368
369/* ea_refcount.c */
370static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret);
371static void ea_refcount_free(ext2_refcount_t refcount);
372static errcode_t ea_refcount_increment(ext2_refcount_t refcount,
373 blk_t blk, int *ret);
374static errcode_t ea_refcount_decrement(ext2_refcount_t refcount,
375 blk_t blk, int *ret);
376static errcode_t ea_refcount_store(ext2_refcount_t refcount,
377 blk_t blk, int count);
378static void ea_refcount_intr_begin(ext2_refcount_t refcount);
379static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret);
380
381/* ehandler.c */
382static const char *ehandler_operation(const char *op);
383static void ehandler_init(io_channel channel);
384
385/* journal.c */
386static int e2fsck_check_ext3_journal(e2fsck_t ctx);
387static int e2fsck_run_ext3_journal(e2fsck_t ctx);
388static void e2fsck_move_ext3_journal(e2fsck_t ctx);
389 366
390/* pass1.c */ 367/* pass1.c */
391static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool); 368static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
392static int e2fsck_pass1_check_device_inode(ext2_filsys fs,
393 struct ext2_inode *inode);
394static int e2fsck_pass1_check_symlink(ext2_filsys fs,
395 struct ext2_inode *inode, char *buf);
396 369
397/* pass2.c */ 370/* pass2.c */
398static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, 371static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
@@ -406,34 +379,15 @@ static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
406static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, 379static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
407 int adj); 380 int adj);
408 381
409
410/* region.c */
411static region_t region_create(region_addr_t min, region_addr_t max);
412static void region_free(region_t region);
413static int region_allocate(region_t region, region_addr_t start, int n);
414
415/* rehash.c */ 382/* rehash.c */
416static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino);
417static void e2fsck_rehash_directories(e2fsck_t ctx); 383static void e2fsck_rehash_directories(e2fsck_t ctx);
418 384
419/* super.c */
420static void check_super_block(e2fsck_t ctx);
421static errcode_t e2fsck_get_device_size(e2fsck_t ctx);
422
423#ifdef ENABLE_SWAPFS
424/* swapfs.c */
425static void swap_filesys(e2fsck_t ctx);
426#endif
427
428/* util.c */ 385/* util.c */
429static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size, 386static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
430 const char *description); 387 const char *description);
431static int ask(e2fsck_t ctx, const char * string, int def); 388static int ask(e2fsck_t ctx, const char * string, int def);
432static int ask_yn(const char * string, int def);
433static void e2fsck_read_bitmaps(e2fsck_t ctx); 389static void e2fsck_read_bitmaps(e2fsck_t ctx);
434static void e2fsck_write_bitmaps(e2fsck_t ctx);
435static void preenhalt(e2fsck_t ctx); 390static void preenhalt(e2fsck_t ctx);
436static char *string_copy(e2fsck_t ctx, const char *str, int len);
437#ifdef RESOURCE_TRACK 391#ifdef RESOURCE_TRACK
438static void print_resource_track(const char *desc, 392static void print_resource_track(const char *desc,
439 struct resource_track *track); 393 struct resource_track *track);
@@ -448,7 +402,6 @@ static void mtrace_print(char *mesg);
448#endif 402#endif
449static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, 403static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
450 const char *name, io_manager manager); 404 const char *name, io_manager manager);
451static int ext2_file_type(unsigned int mode);
452 405
453/* unix.c */ 406/* unix.c */
454static void e2fsck_clear_progbar(e2fsck_t ctx); 407static void e2fsck_clear_progbar(e2fsck_t ctx);
@@ -477,15 +430,15 @@ struct problem_context {
477 * handled as a set. The user answers once for a particular latch 430 * handled as a set. The user answers once for a particular latch
478 * group. 431 * group.
479 */ 432 */
480#define PR_LATCH_MASK 0x0ff0 /* Latch mask */ 433#define PR_LATCH_MASK 0x0ff0 /* Latch mask */
481#define PR_LATCH_BLOCK 0x0010 /* Latch for illegal blocks (pass 1) */ 434#define PR_LATCH_BLOCK 0x0010 /* Latch for illegal blocks (pass 1) */
482#define PR_LATCH_BBLOCK 0x0020 /* Latch for bad block inode blocks (pass 1) */ 435#define PR_LATCH_BBLOCK 0x0020 /* Latch for bad block inode blocks (pass 1) */
483#define PR_LATCH_IBITMAP 0x0030 /* Latch for pass 5 inode bitmap proc. */ 436#define PR_LATCH_IBITMAP 0x0030 /* Latch for pass 5 inode bitmap proc. */
484#define PR_LATCH_BBITMAP 0x0040 /* Latch for pass 5 inode bitmap proc. */ 437#define PR_LATCH_BBITMAP 0x0040 /* Latch for pass 5 inode bitmap proc. */
485#define PR_LATCH_RELOC 0x0050 /* Latch for superblock relocate hint */ 438#define PR_LATCH_RELOC 0x0050 /* Latch for superblock relocate hint */
486#define PR_LATCH_DBLOCK 0x0060 /* Latch for pass 1b dup block headers */ 439#define PR_LATCH_DBLOCK 0x0060 /* Latch for pass 1b dup block headers */
487#define PR_LATCH_LOW_DTIME 0x0070 /* Latch for pass1 orphaned list refugees */ 440#define PR_LATCH_LOW_DTIME 0x0070 /* Latch for pass1 orphaned list refugees */
488#define PR_LATCH_TOOBIG 0x0080 /* Latch for file to big errors */ 441#define PR_LATCH_TOOBIG 0x0080 /* Latch for file to big errors */
489#define PR_LATCH_OPTIMIZE_DIR 0x0090 /* Latch for optimize directories */ 442#define PR_LATCH_OPTIMIZE_DIR 0x0090 /* Latch for optimize directories */
490 443
491#define PR_LATCH(x) ((((x) & PR_LATCH_MASK) >> 4) - 1) 444#define PR_LATCH(x) ((((x) & PR_LATCH_MASK) >> 4) - 1)
@@ -1339,28 +1292,12 @@ static int end_problem_latch(e2fsck_t ctx, int mask);
1339static int set_latch_flags(int mask, int setflags, int clearflags); 1292static int set_latch_flags(int mask, int setflags, int clearflags);
1340static void clear_problem_context(struct problem_context *ctx); 1293static void clear_problem_context(struct problem_context *ctx);
1341 1294
1342/* message.c */
1343static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
1344 struct problem_context *pctx, int first);
1345
1346/* 1295/*
1347 * Dictionary Abstract Data Type 1296 * Dictionary Abstract Data Type
1348 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net> 1297 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
1349 * 1298 *
1350 * Free Software License: 1299 * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
1351 * 1300 * kazlib_1_20
1352 * All rights are reserved by the author, with the following exceptions:
1353 * Permission is granted to freely reproduce and distribute this software,
1354 * possibly in exchange for a fee, provided that this copyright notice appears
1355 * intact. Permission is also granted to adapt this software to produce
1356 * derivative works, as long as the modified versions carry this copyright
1357 * notice and additional notices stating that the work has been modified.
1358 * This source code may be translated into executable form and incorporated
1359 * into proprietary software; there is no requirement for such software to
1360 * contain a copyright notice related to this source.
1361 *
1362 * $Id: dict.h,v 1.22.2.6 2000/11/13 01:36:44 kaz Exp $
1363 * $Name: kazlib_1_20 $
1364 */ 1301 */
1365 1302
1366#ifndef DICT_H 1303#ifndef DICT_H
@@ -1389,17 +1326,14 @@ typedef struct dnode_t {
1389} dnode_t; 1326} dnode_t;
1390 1327
1391typedef int (*dict_comp_t)(const void *, const void *); 1328typedef int (*dict_comp_t)(const void *, const void *);
1392typedef dnode_t *(*dnode_alloc_t)(void *); 1329typedef void (*dnode_free_t)(dnode_t *);
1393typedef void (*dnode_free_t)(dnode_t *, void *);
1394 1330
1395typedef struct dict_t { 1331typedef struct dict_t {
1396 dnode_t dict_nilnode; 1332 dnode_t dict_nilnode;
1397 dictcount_t dict_nodecount; 1333 dictcount_t dict_nodecount;
1398 dictcount_t dict_maxcount; 1334 dictcount_t dict_maxcount;
1399 dict_comp_t dict_compare; 1335 dict_comp_t dict_compare;
1400 dnode_alloc_t dict_allocnode;
1401 dnode_free_t dict_freenode; 1336 dnode_free_t dict_freenode;
1402 void *dict_context;
1403 int dict_dupes; 1337 int dict_dupes;
1404} dict_t; 1338} dict_t;
1405 1339
@@ -1410,19 +1344,6 @@ typedef struct dict_load_t {
1410 dnode_t dict_nilnode; 1344 dnode_t dict_nilnode;
1411} dict_load_t; 1345} dict_load_t;
1412 1346
1413static void dict_set_allocator(dict_t *, dnode_alloc_t, dnode_free_t, void *);
1414static void dict_free_nodes(dict_t *);
1415static dict_t *dict_init(dict_t *, dictcount_t, dict_comp_t);
1416static dnode_t *dict_lookup(dict_t *, const void *);
1417static void dict_insert(dict_t *, dnode_t *, const void *);
1418static int dict_alloc_insert(dict_t *, const void *, void *);
1419static dnode_t *dict_first(dict_t *);
1420static dnode_t *dict_next(dict_t *, dnode_t *);
1421static dictcount_t dict_count(dict_t *);
1422static dnode_t *dnode_init(dnode_t *, void *);
1423static void *dnode_get(dnode_t *);
1424static const void *dnode_getkey(dnode_t *);
1425
1426#define dict_count(D) ((D)->dict_nodecount) 1347#define dict_count(D) ((D)->dict_nodecount)
1427#define dnode_get(N) ((N)->dict_data) 1348#define dnode_get(N) ((N)->dict_data)
1428#define dnode_getkey(N) ((N)->dict_key) 1349#define dnode_getkey(N) ((N)->dict_key)
@@ -1480,11 +1401,6 @@ typedef struct {
1480} kmem_cache_t; 1401} kmem_cache_t;
1481 1402
1482#define kmem_cache_alloc(cache,flags) malloc((cache)->object_length) 1403#define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
1483#define kmem_cache_free(cache,obj) free(obj)
1484#define kmem_cache_create(name,len,a,b,c,d) do_cache_create(len)
1485#define kmem_cache_destroy(cache) do_cache_destroy(cache)
1486#define kmalloc(len,flags) malloc(len)
1487#define kfree(p) free(p)
1488 1404
1489/* 1405/*
1490 * We use the standard libext2fs portability tricks for inline 1406 * We use the standard libext2fs portability tricks for inline
@@ -1494,6 +1410,7 @@ typedef struct {
1494static _INLINE_ kmem_cache_t * do_cache_create(int len) 1410static _INLINE_ kmem_cache_t * do_cache_create(int len)
1495{ 1411{
1496 kmem_cache_t *new_cache; 1412 kmem_cache_t *new_cache;
1413
1497 new_cache = malloc(sizeof(*new_cache)); 1414 new_cache = malloc(sizeof(*new_cache));
1498 if (new_cache) 1415 if (new_cache)
1499 new_cache->object_length = len; 1416 new_cache->object_length = len;
@@ -1511,29 +1428,7 @@ static _INLINE_ void do_cache_destroy(kmem_cache_t *cache)
1511#include "ext2fs/kernel-jbd.h" 1428#include "ext2fs/kernel-jbd.h"
1512 1429
1513/* 1430/*
1514 * Kernel compatibility functions are defined in journal.c
1515 */
1516static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys);
1517static struct buffer_head *getblk(kdev_t ctx, blk_t blocknr, int blocksize);
1518static void sync_blockdev(kdev_t kdev);
1519static void ll_rw_block(int rw, int dummy, struct buffer_head *bh[]);
1520static void mark_buffer_dirty(struct buffer_head *bh);
1521static void mark_buffer_uptodate(struct buffer_head *bh, int val);
1522static void brelse(struct buffer_head *bh);
1523static int buffer_uptodate(struct buffer_head *bh);
1524static void wait_on_buffer(struct buffer_head *bh);
1525
1526/*
1527 * Define newer 2.5 interfaces
1528 */
1529#define __getblk(dev, blocknr, blocksize) getblk(dev, blocknr, blocksize)
1530#define set_buffer_uptodate(bh) mark_buffer_uptodate(bh, 1)
1531
1532/*
1533 * badblocks.c --- replace/append bad blocks to the bad block inode 1431 * badblocks.c --- replace/append bad blocks to the bad block inode
1534 *
1535 * Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
1536 * redistributed under the terms of the GNU Public License.
1537 */ 1432 */
1538 1433
1539static int check_bb_inode_blocks(ext2_filsys fs, blk_t *block_nr, int blockcnt, 1434static int check_bb_inode_blocks(ext2_filsys fs, blk_t *block_nr, int blockcnt,
@@ -1546,7 +1441,7 @@ static void invalid_block(ext2_filsys fs EXT2FS_ATTR((unused)), blk_t blk)
1546 return; 1441 return;
1547} 1442}
1548 1443
1549void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file, 1444static void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file,
1550 int replace_bad_blocks) 1445 int replace_bad_blocks)
1551{ 1446{
1552 ext2_filsys fs = ctx->fs; 1447 ext2_filsys fs = ctx->fs;
@@ -1659,22 +1554,6 @@ static int check_bb_inode_blocks(ext2_filsys fs,
1659 1554
1660/* 1555/*
1661 * Dictionary Abstract Data Type 1556 * Dictionary Abstract Data Type
1662 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
1663 *
1664 * Free Software License:
1665 *
1666 * All rights are reserved by the author, with the following exceptions:
1667 * Permission is granted to freely reproduce and distribute this software,
1668 * possibly in exchange for a fee, provided that this copyright notice appears
1669 * intact. Permission is also granted to adapt this software to produce
1670 * derivative works, as long as the modified versions carry this copyright
1671 * notice and additional notices stating that the work has been modified.
1672 * This source code may be translated into executable form and incorporated
1673 * into proprietary software; there is no requirement for such software to
1674 * contain a copyright notice related to this source.
1675 *
1676 * $Id: dict.c,v 1.40.2.7 2000/11/13 01:36:44 kaz Exp $
1677 * $Name: kazlib_1_20 $
1678 */ 1557 */
1679 1558
1680 1559
@@ -1698,22 +1577,15 @@ static int check_bb_inode_blocks(ext2_filsys fs,
1698#define data dict_data 1577#define data dict_data
1699 1578
1700#define nilnode dict_nilnode 1579#define nilnode dict_nilnode
1701#define nodecount dict_nodecount
1702#define maxcount dict_maxcount 1580#define maxcount dict_maxcount
1703#define compare dict_compare 1581#define compare dict_compare
1704#define allocnode dict_allocnode
1705#define freenode dict_freenode
1706#define context dict_context
1707#define dupes dict_dupes 1582#define dupes dict_dupes
1708 1583
1709#define dictptr dict_dictptr
1710
1711#define dict_root(D) ((D)->nilnode.left) 1584#define dict_root(D) ((D)->nilnode.left)
1712#define dict_nil(D) (&(D)->nilnode) 1585#define dict_nil(D) (&(D)->nilnode)
1713#define DICT_DEPTH_MAX 64 1586#define DICT_DEPTH_MAX 64
1714 1587
1715static dnode_t *dnode_alloc(void *context); 1588static void dnode_free(dnode_t *node);
1716static void dnode_free(dnode_t *node, void *context);
1717 1589
1718/* 1590/*
1719 * Perform a ``left rotation'' adjustment on the tree. The given node P and 1591 * Perform a ``left rotation'' adjustment on the tree. The given node P and
@@ -1783,7 +1655,7 @@ static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
1783 return; 1655 return;
1784 free_nodes(dict, node->left, nil); 1656 free_nodes(dict, node->left, nil);
1785 free_nodes(dict, node->right, nil); 1657 free_nodes(dict, node->right, nil);
1786 dict->freenode(node, dict->context); 1658 dict->dict_freenode(node);
1787} 1659}
1788 1660
1789/* 1661/*
@@ -1808,15 +1680,10 @@ static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
1808 * Select a different set of node allocator routines. 1680 * Select a different set of node allocator routines.
1809 */ 1681 */
1810 1682
1811void dict_set_allocator(dict_t *dict, dnode_alloc_t al, 1683static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
1812 dnode_free_t fr, void *context)
1813{ 1684{
1814 assert (dict_count(dict) == 0); 1685 assert (dict_count(dict) == 0);
1815 assert ((al == NULL && fr == NULL) || (al != NULL && fr != NULL)); 1686 dict->dict_freenode = fr;
1816
1817 dict->allocnode = al ? al : dnode_alloc;
1818 dict->freenode = fr ? fr : dnode_free;
1819 dict->context = context;
1820} 1687}
1821 1688
1822/* 1689/*
@@ -1824,11 +1691,11 @@ void dict_set_allocator(dict_t *dict, dnode_alloc_t al,
1824 * installed free routine. The dictionary is emptied. 1691 * installed free routine. The dictionary is emptied.
1825 */ 1692 */
1826 1693
1827void dict_free_nodes(dict_t *dict) 1694static void dict_free_nodes(dict_t *dict)
1828{ 1695{
1829 dnode_t *nil = dict_nil(dict), *root = dict_root(dict); 1696 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
1830 free_nodes(dict, root, nil); 1697 free_nodes(dict, root, nil);
1831 dict->nodecount = 0; 1698 dict->dict_nodecount = 0;
1832 dict->nilnode.left = &dict->nilnode; 1699 dict->nilnode.left = &dict->nilnode;
1833 dict->nilnode.right = &dict->nilnode; 1700 dict->nilnode.right = &dict->nilnode;
1834} 1701}
@@ -1837,13 +1704,11 @@ void dict_free_nodes(dict_t *dict)
1837 * Initialize a user-supplied dictionary object. 1704 * Initialize a user-supplied dictionary object.
1838 */ 1705 */
1839 1706
1840dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp) 1707static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
1841{ 1708{
1842 dict->compare = comp; 1709 dict->compare = comp;
1843 dict->allocnode = dnode_alloc; 1710 dict->dict_freenode = dnode_free;
1844 dict->freenode = dnode_free; 1711 dict->dict_nodecount = 0;
1845 dict->context = NULL;
1846 dict->nodecount = 0;
1847 dict->maxcount = maxcount; 1712 dict->maxcount = maxcount;
1848 dict->nilnode.left = &dict->nilnode; 1713 dict->nilnode.left = &dict->nilnode;
1849 dict->nilnode.right = &dict->nilnode; 1714 dict->nilnode.right = &dict->nilnode;
@@ -1860,7 +1725,7 @@ dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
1860 * located node is returned. 1725 * located node is returned.
1861 */ 1726 */
1862 1727
1863dnode_t *dict_lookup(dict_t *dict, const void *key) 1728static dnode_t *dict_lookup(dict_t *dict, const void *key)
1864{ 1729{
1865 dnode_t *root = dict_root(dict); 1730 dnode_t *root = dict_root(dict);
1866 dnode_t *nil = dict_nil(dict); 1731 dnode_t *nil = dict_nil(dict);
@@ -1901,7 +1766,7 @@ dnode_t *dict_lookup(dict_t *dict, const void *key)
1901 * function returns true). 1766 * function returns true).
1902 */ 1767 */
1903 1768
1904void dict_insert(dict_t *dict, dnode_t *node, const void *key) 1769static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
1905{ 1770{
1906 dnode_t *where = dict_root(dict), *nil = dict_nil(dict); 1771 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
1907 dnode_t *parent = nil, *uncle, *grandpa; 1772 dnode_t *parent = nil, *uncle, *grandpa;
@@ -1933,7 +1798,7 @@ void dict_insert(dict_t *dict, dnode_t *node, const void *key)
1933 node->left = nil; 1798 node->left = nil;
1934 node->right = nil; 1799 node->right = nil;
1935 1800
1936 dict->nodecount++; 1801 dict->dict_nodecount++;
1937 1802
1938 /* red black adjustments */ 1803 /* red black adjustments */
1939 1804
@@ -1992,9 +1857,18 @@ void dict_insert(dict_t *dict, dnode_t *node, const void *key)
1992 * the data item. 1857 * the data item.
1993 */ 1858 */
1994 1859
1995int dict_alloc_insert(dict_t *dict, const void *key, void *data) 1860static dnode_t *dnode_init(dnode_t *dnode, void *data)
1996{ 1861{
1997 dnode_t *node = dict->allocnode(dict->context); 1862 dnode->data = data;
1863 dnode->parent = NULL;
1864 dnode->left = NULL;
1865 dnode->right = NULL;
1866 return dnode;
1867}
1868
1869static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
1870{
1871 dnode_t *node = malloc(sizeof(dnode_t));
1998 1872
1999 if (node) { 1873 if (node) {
2000 dnode_init(node, data); 1874 dnode_init(node, data);
@@ -2009,7 +1883,7 @@ int dict_alloc_insert(dict_t *dict, const void *key, void *data)
2009 * (that is, dict_isempty(dict) returns 1) a null pointer is returned. 1883 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
2010 */ 1884 */
2011 1885
2012dnode_t *dict_first(dict_t *dict) 1886static dnode_t *dict_first(dict_t *dict)
2013{ 1887{
2014 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left; 1888 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
2015 1889
@@ -2027,7 +1901,7 @@ dnode_t *dict_first(dict_t *dict)
2027 * the nil node. 1901 * the nil node.
2028 */ 1902 */
2029 1903
2030dnode_t *dict_next(dict_t *dict, dnode_t *curr) 1904static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
2031{ 1905{
2032 dnode_t *nil = dict_nil(dict), *parent, *left; 1906 dnode_t *nil = dict_nil(dict), *parent, *left;
2033 1907
@@ -2048,43 +1922,12 @@ dnode_t *dict_next(dict_t *dict, dnode_t *curr)
2048 return (parent == nil) ? NULL : parent; 1922 return (parent == nil) ? NULL : parent;
2049} 1923}
2050 1924
2051#undef dict_count
2052#undef dnode_get
2053#undef dnode_getkey
2054
2055dictcount_t dict_count(dict_t *dict)
2056{
2057 return dict->nodecount;
2058}
2059
2060static dnode_t *dnode_alloc(void *context EXT2FS_ATTR((unused)))
2061{
2062 return malloc(sizeof *dnode_alloc(NULL));
2063}
2064 1925
2065static void dnode_free(dnode_t *node, void *context EXT2FS_ATTR((unused))) 1926static void dnode_free(dnode_t *node)
2066{ 1927{
2067 free(node); 1928 free(node);
2068} 1929}
2069 1930
2070dnode_t *dnode_init(dnode_t *dnode, void *data)
2071{
2072 dnode->data = data;
2073 dnode->parent = NULL;
2074 dnode->left = NULL;
2075 dnode->right = NULL;
2076 return dnode;
2077}
2078
2079void *dnode_get(dnode_t *dnode)
2080{
2081 return dnode->data;
2082}
2083
2084const void *dnode_getkey(dnode_t *dnode)
2085{
2086 return dnode->key;
2087}
2088 1931
2089#undef left 1932#undef left
2090#undef right 1933#undef right
@@ -2094,22 +1937,13 @@ const void *dnode_getkey(dnode_t *dnode)
2094#undef data 1937#undef data
2095 1938
2096#undef nilnode 1939#undef nilnode
2097#undef nodecount
2098#undef maxcount 1940#undef maxcount
2099#undef compare 1941#undef compare
2100#undef allocnode
2101#undef freenode
2102#undef context
2103#undef dupes 1942#undef dupes
2104 1943
2105#undef dictptr
2106
2107 1944
2108/* 1945/*
2109 * dirinfo.c --- maintains the directory information table for e2fsck. 1946 * dirinfo.c --- maintains the directory information table for e2fsck.
2110 *
2111 * Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
2112 * under the terms of the GNU Public License.
2113 */ 1947 */
2114 1948
2115/* 1949/*
@@ -2117,7 +1951,7 @@ const void *dnode_getkey(dnode_t *dnode)
2117 * entry. During pass1, the passed-in parent is 0; it will get filled 1951 * entry. During pass1, the passed-in parent is 0; it will get filled
2118 * in during pass2. 1952 * in during pass2.
2119 */ 1953 */
2120void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent) 1954static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
2121{ 1955{
2122 struct dir_info *dir; 1956 struct dir_info *dir;
2123 int i, j; 1957 int i, j;
@@ -2182,7 +2016,7 @@ void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
2182 * get_dir_info() --- given an inode number, try to find the directory 2016 * get_dir_info() --- given an inode number, try to find the directory
2183 * information entry for it. 2017 * information entry for it.
2184 */ 2018 */
2185struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino) 2019static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
2186{ 2020{
2187 int low, high, mid; 2021 int low, high, mid;
2188 2022
@@ -2212,7 +2046,7 @@ struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
2212/* 2046/*
2213 * Free the dir_info structure when it isn't needed any more. 2047 * Free the dir_info structure when it isn't needed any more.
2214 */ 2048 */
2215void e2fsck_free_dir_info(e2fsck_t ctx) 2049static void e2fsck_free_dir_info(e2fsck_t ctx)
2216{ 2050{
2217 if (ctx->dir_info) { 2051 if (ctx->dir_info) {
2218 ext2fs_free_mem(&ctx->dir_info); 2052 ext2fs_free_mem(&ctx->dir_info);
@@ -2225,7 +2059,7 @@ void e2fsck_free_dir_info(e2fsck_t ctx)
2225/* 2059/*
2226 * Return the count of number of directories in the dir_info structure 2060 * Return the count of number of directories in the dir_info structure
2227 */ 2061 */
2228int e2fsck_get_num_dirinfo(e2fsck_t ctx) 2062static inline int e2fsck_get_num_dirinfo(e2fsck_t ctx)
2229{ 2063{
2230 return ctx->dir_info_count; 2064 return ctx->dir_info_count;
2231} 2065}
@@ -2233,18 +2067,17 @@ int e2fsck_get_num_dirinfo(e2fsck_t ctx)
2233/* 2067/*
2234 * A simple interator function 2068 * A simple interator function
2235 */ 2069 */
2236struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control) 2070static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
2237{ 2071{
2238 if (*control >= ctx->dir_info_count) 2072 if (*control >= ctx->dir_info_count)
2239 return 0; 2073 return 0;
2240 2074
2241 return(ctx->dir_info + (*control)++); 2075 return(ctx->dir_info + (*control)++);
2242} 2076}
2077
2243/* 2078/*
2244 * dirinfo.c --- maintains the directory information table for e2fsck. 2079 * dirinfo.c --- maintains the directory information table for e2fsck.
2245 * 2080 *
2246 * Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
2247 * under the terms of the GNU Public License.
2248 */ 2081 */
2249 2082
2250#ifdef ENABLE_HTREE 2083#ifdef ENABLE_HTREE
@@ -2254,7 +2087,7 @@ struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
2254 * entry. During pass1, the passed-in parent is 0; it will get filled 2087 * entry. During pass1, the passed-in parent is 0; it will get filled
2255 * in during pass2. 2088 * in during pass2.
2256 */ 2089 */
2257void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks) 2090static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
2258{ 2091{
2259 struct dx_dir_info *dir; 2092 struct dx_dir_info *dir;
2260 int i, j; 2093 int i, j;
@@ -2319,7 +2152,7 @@ void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
2319 * get_dx_dir_info() --- given an inode number, try to find the directory 2152 * get_dx_dir_info() --- given an inode number, try to find the directory
2320 * information entry for it. 2153 * information entry for it.
2321 */ 2154 */
2322struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino) 2155static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
2323{ 2156{
2324 int low, high, mid; 2157 int low, high, mid;
2325 2158
@@ -2349,7 +2182,7 @@ struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
2349/* 2182/*
2350 * Free the dx_dir_info structure when it isn't needed any more. 2183 * Free the dx_dir_info structure when it isn't needed any more.
2351 */ 2184 */
2352void e2fsck_free_dx_dir_info(e2fsck_t ctx) 2185static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
2353{ 2186{
2354 int i; 2187 int i;
2355 struct dx_dir_info *dir; 2188 struct dx_dir_info *dir;
@@ -2372,7 +2205,7 @@ void e2fsck_free_dx_dir_info(e2fsck_t ctx)
2372/* 2205/*
2373 * A simple interator function 2206 * A simple interator function
2374 */ 2207 */
2375struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control) 2208static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
2376{ 2209{
2377 if (*control >= ctx->dx_dir_info_count) 2210 if (*control >= ctx->dx_dir_info_count)
2378 return 0; 2211 return 0;
@@ -2384,18 +2217,12 @@ struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
2384/* 2217/*
2385 * e2fsck.c - a consistency checker for the new extended file system. 2218 * e2fsck.c - a consistency checker for the new extended file system.
2386 * 2219 *
2387 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
2388 *
2389 * %Begin-Header%
2390 * This file may be redistributed under the terms of the GNU Public
2391 * License.
2392 * %End-Header%
2393 */ 2220 */
2394 2221
2395/* 2222/*
2396 * This function allocates an e2fsck context 2223 * This function allocates an e2fsck context
2397 */ 2224 */
2398errcode_t e2fsck_allocate_context(e2fsck_t *ret) 2225static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
2399{ 2226{
2400 e2fsck_t context; 2227 e2fsck_t context;
2401 errcode_t retval; 2228 errcode_t retval;
@@ -2413,11 +2240,33 @@ errcode_t e2fsck_allocate_context(e2fsck_t *ret)
2413 return 0; 2240 return 0;
2414} 2241}
2415 2242
2243struct ea_refcount_el {
2244 blk_t ea_blk;
2245 int ea_count;
2246};
2247
2248struct ea_refcount {
2249 blk_t count;
2250 blk_t size;
2251 blk_t cursor;
2252 struct ea_refcount_el *list;
2253};
2254
2255static void ea_refcount_free(ext2_refcount_t refcount)
2256{
2257 if (!refcount)
2258 return;
2259
2260 if (refcount->list)
2261 ext2fs_free_mem(&refcount->list);
2262 ext2fs_free_mem(&refcount);
2263}
2264
2416/* 2265/*
2417 * This function resets an e2fsck context; it is called when e2fsck 2266 * This function resets an e2fsck context; it is called when e2fsck
2418 * needs to be restarted. 2267 * needs to be restarted.
2419 */ 2268 */
2420errcode_t e2fsck_reset_context(e2fsck_t ctx) 2269static errcode_t e2fsck_reset_context(e2fsck_t ctx)
2421{ 2270{
2422 ctx->flags = 0; 2271 ctx->flags = 0;
2423 ctx->lost_and_found = 0; 2272 ctx->lost_and_found = 0;
@@ -2528,7 +2377,7 @@ errcode_t e2fsck_reset_context(e2fsck_t ctx)
2528 return 0; 2377 return 0;
2529} 2378}
2530 2379
2531void e2fsck_free_context(e2fsck_t ctx) 2380static void e2fsck_free_context(e2fsck_t ctx)
2532{ 2381{
2533 if (!ctx) 2382 if (!ctx)
2534 return; 2383 return;
@@ -2541,46 +2390,7 @@ void e2fsck_free_context(e2fsck_t ctx)
2541} 2390}
2542 2391
2543/* 2392/*
2544 * This function runs through the e2fsck passes and calls them all,
2545 * returning restart, abort, or cancel as necessary...
2546 */
2547typedef void (*pass_t)(e2fsck_t ctx);
2548
2549static pass_t e2fsck_passes[] = {
2550 e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
2551 e2fsck_pass5, 0 };
2552
2553#define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
2554
2555int e2fsck_run(e2fsck_t ctx)
2556{
2557 int i;
2558 pass_t e2fsck_pass;
2559
2560 if (setjmp(ctx->abort_loc)) {
2561 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
2562 return (ctx->flags & E2F_FLAG_RUN_RETURN);
2563 }
2564 ctx->flags |= E2F_FLAG_SETJMP_OK;
2565
2566 for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
2567 if (ctx->flags & E2F_FLAG_RUN_RETURN)
2568 break;
2569 e2fsck_pass(ctx);
2570 if (ctx->progress)
2571 (void) (ctx->progress)(ctx, 0, 0, 0);
2572 }
2573 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
2574
2575 if (ctx->flags & E2F_FLAG_RUN_RETURN)
2576 return (ctx->flags & E2F_FLAG_RUN_RETURN);
2577 return 0;
2578}
2579/*
2580 * ea_refcount.c 2393 * ea_refcount.c
2581 *
2582 * Copyright (C) 2001 Theodore Ts'o. This file may be
2583 * redistributed under the terms of the GNU Public License.
2584 */ 2394 */
2585 2395
2586/* 2396/*
@@ -2590,29 +2400,9 @@ int e2fsck_run(e2fsck_t ctx)
2590 * removed from the array to save memory space. Once the EA block is 2400 * removed from the array to save memory space. Once the EA block is
2591 * checked, its bit is set in the block_ea_map bitmap. 2401 * checked, its bit is set in the block_ea_map bitmap.
2592 */ 2402 */
2593struct ea_refcount_el {
2594 blk_t ea_blk;
2595 int ea_count;
2596};
2597
2598struct ea_refcount {
2599 blk_t count;
2600 blk_t size;
2601 blk_t cursor;
2602 struct ea_refcount_el *list;
2603};
2604
2605void ea_refcount_free(ext2_refcount_t refcount)
2606{
2607 if (!refcount)
2608 return;
2609 2403
2610 if (refcount->list)
2611 ext2fs_free_mem(&refcount->list);
2612 ext2fs_free_mem(&refcount);
2613}
2614 2404
2615errcode_t ea_refcount_create(int size, ext2_refcount_t *ret) 2405static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
2616{ 2406{
2617 ext2_refcount_t refcount; 2407 ext2_refcount_t refcount;
2618 errcode_t retval; 2408 errcode_t retval;
@@ -2793,7 +2583,8 @@ retry:
2793 return 0; 2583 return 0;
2794} 2584}
2795 2585
2796errcode_t ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret) 2586static errcode_t
2587ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
2797{ 2588{
2798 struct ea_refcount_el *el; 2589 struct ea_refcount_el *el;
2799 2590
@@ -2807,7 +2598,8 @@ errcode_t ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
2807 return 0; 2598 return 0;
2808} 2599}
2809 2600
2810errcode_t ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret) 2601static errcode_t
2602ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
2811{ 2603{
2812 struct ea_refcount_el *el; 2604 struct ea_refcount_el *el;
2813 2605
@@ -2822,7 +2614,8 @@ errcode_t ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
2822 return 0; 2614 return 0;
2823} 2615}
2824 2616
2825errcode_t ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count) 2617static errcode_t
2618ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
2826{ 2619{
2827 struct ea_refcount_el *el; 2620 struct ea_refcount_el *el;
2828 2621
@@ -2836,14 +2629,13 @@ errcode_t ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
2836 return 0; 2629 return 0;
2837} 2630}
2838 2631
2839void ea_refcount_intr_begin(ext2_refcount_t refcount) 2632static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
2840{ 2633{
2841 refcount->cursor = 0; 2634 refcount->cursor = 0;
2842} 2635}
2843 2636
2844 2637
2845blk_t ea_refcount_intr_next(ext2_refcount_t refcount, 2638static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
2846 int *ret)
2847{ 2639{
2848 struct ea_refcount_el *list; 2640 struct ea_refcount_el *list;
2849 2641
@@ -2864,21 +2656,15 @@ blk_t ea_refcount_intr_next(ext2_refcount_t refcount,
2864/* 2656/*
2865 * ehandler.c --- handle bad block errors which come up during the 2657 * ehandler.c --- handle bad block errors which come up during the
2866 * course of an e2fsck session. 2658 * course of an e2fsck session.
2867 *
2868 * Copyright (C) 1994 Theodore Ts'o. This file may be redistributed
2869 * under the terms of the GNU Public License.
2870 */ 2659 */
2871 2660
2872 2661
2873static const char *operation; 2662static const char *operation;
2874 2663
2875static errcode_t e2fsck_handle_read_error(io_channel channel, 2664static errcode_t
2876 unsigned long block, 2665e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
2877 int count, 2666 void *data, size_t size EXT2FS_ATTR((unused)),
2878 void *data, 2667 int actual EXT2FS_ATTR((unused)), errcode_t error)
2879 size_t size EXT2FS_ATTR((unused)),
2880 int actual EXT2FS_ATTR((unused)),
2881 errcode_t error)
2882{ 2668{
2883 int i; 2669 int i;
2884 char *p; 2670 char *p;
@@ -2918,13 +2704,10 @@ static errcode_t e2fsck_handle_read_error(io_channel channel,
2918 return error; 2704 return error;
2919} 2705}
2920 2706
2921static errcode_t e2fsck_handle_write_error(io_channel channel, 2707static errcode_t
2922 unsigned long block, 2708e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
2923 int count, 2709 const void *data, size_t size EXT2FS_ATTR((unused)),
2924 const void *data, 2710 int actual EXT2FS_ATTR((unused)), errcode_t error)
2925 size_t size EXT2FS_ATTR((unused)),
2926 int actual EXT2FS_ATTR((unused)),
2927 errcode_t error)
2928{ 2711{
2929 int i; 2712 int i;
2930 const char *p; 2713 const char *p;
@@ -2962,7 +2745,7 @@ static errcode_t e2fsck_handle_write_error(io_channel channel,
2962 return error; 2745 return error;
2963} 2746}
2964 2747
2965const char *ehandler_operation(const char *op) 2748static inline const char *ehandler_operation(const char *op)
2966{ 2749{
2967 const char *ret = operation; 2750 const char *ret = operation;
2968 2751
@@ -2970,11 +2753,12 @@ const char *ehandler_operation(const char *op)
2970 return ret; 2753 return ret;
2971} 2754}
2972 2755
2973void ehandler_init(io_channel channel) 2756static void ehandler_init(io_channel channel)
2974{ 2757{
2975 channel->read_error = e2fsck_handle_read_error; 2758 channel->read_error = e2fsck_handle_read_error;
2976 channel->write_error = e2fsck_handle_write_error; 2759 channel->write_error = e2fsck_handle_write_error;
2977} 2760}
2761
2978/* 2762/*
2979 * journal.c --- code for handling the "ext3" journal 2763 * journal.c --- code for handling the "ext3" journal
2980 * 2764 *
@@ -3009,7 +2793,7 @@ static int bh_count = 0;
3009 * to use the recovery.c file virtually unchanged from the kernel, so we 2793 * to use the recovery.c file virtually unchanged from the kernel, so we
3010 * don't have to do much to keep kernel and user recovery in sync. 2794 * don't have to do much to keep kernel and user recovery in sync.
3011 */ 2795 */
3012int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys) 2796static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
3013{ 2797{
3014#ifdef USE_INODE_IO 2798#ifdef USE_INODE_IO
3015 *phys = block; 2799 *phys = block;
@@ -3031,7 +2815,7 @@ int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
3031#endif 2815#endif
3032} 2816}
3033 2817
3034struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize) 2818static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
3035{ 2819{
3036 struct buffer_head *bh; 2820 struct buffer_head *bh;
3037 2821
@@ -3053,7 +2837,7 @@ struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
3053 return bh; 2837 return bh;
3054} 2838}
3055 2839
3056void sync_blockdev(kdev_t kdev) 2840static void sync_blockdev(kdev_t kdev)
3057{ 2841{
3058 io_channel io; 2842 io_channel io;
3059 2843
@@ -3065,7 +2849,7 @@ void sync_blockdev(kdev_t kdev)
3065 io_channel_flush(io); 2849 io_channel_flush(io);
3066} 2850}
3067 2851
3068void ll_rw_block(int rw, int nr, struct buffer_head *bhp[]) 2852static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
3069{ 2853{
3070 int retval; 2854 int retval;
3071 struct buffer_head *bh; 2855 struct buffer_head *bh;
@@ -3109,17 +2893,17 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
3109 } 2893 }
3110} 2894}
3111 2895
3112void mark_buffer_dirty(struct buffer_head *bh) 2896static inline void mark_buffer_dirty(struct buffer_head *bh)
3113{ 2897{
3114 bh->b_dirty = 1; 2898 bh->b_dirty = 1;
3115} 2899}
3116 2900
3117static void mark_buffer_clean(struct buffer_head * bh) 2901static inline void mark_buffer_clean(struct buffer_head * bh)
3118{ 2902{
3119 bh->b_dirty = 0; 2903 bh->b_dirty = 0;
3120} 2904}
3121 2905
3122void brelse(struct buffer_head *bh) 2906static void brelse(struct buffer_head *bh)
3123{ 2907{
3124 if (bh->b_dirty) 2908 if (bh->b_dirty)
3125 ll_rw_block(WRITE, 1, &bh); 2909 ll_rw_block(WRITE, 1, &bh);
@@ -3128,17 +2912,17 @@ void brelse(struct buffer_head *bh)
3128 ext2fs_free_mem(&bh); 2912 ext2fs_free_mem(&bh);
3129} 2913}
3130 2914
3131int buffer_uptodate(struct buffer_head *bh) 2915static inline int buffer_uptodate(struct buffer_head *bh)
3132{ 2916{
3133 return bh->b_uptodate; 2917 return bh->b_uptodate;
3134} 2918}
3135 2919
3136void mark_buffer_uptodate(struct buffer_head *bh, int val) 2920static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
3137{ 2921{
3138 bh->b_uptodate = val; 2922 bh->b_uptodate = val;
3139} 2923}
3140 2924
3141void wait_on_buffer(struct buffer_head *bh) 2925static void wait_on_buffer(struct buffer_head *bh)
3142{ 2926{
3143 if (!bh->b_uptodate) 2927 if (!bh->b_uptodate)
3144 ll_rw_block(READ, 1, &bh); 2928 ll_rw_block(READ, 1, &bh);
@@ -3608,7 +3392,7 @@ static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
3608 * This function makes sure that the superblock fields regarding the 3392 * This function makes sure that the superblock fields regarding the
3609 * journal are consistent. 3393 * journal are consistent.
3610 */ 3394 */
3611int e2fsck_check_ext3_journal(e2fsck_t ctx) 3395static int e2fsck_check_ext3_journal(e2fsck_t ctx)
3612{ 3396{
3613 struct ext2_super_block *sb = ctx->fs->super; 3397 struct ext2_super_block *sb = ctx->fs->super;
3614 journal_t *journal; 3398 journal_t *journal;
@@ -3759,7 +3543,7 @@ errout:
3759 return retval; 3543 return retval;
3760} 3544}
3761 3545
3762int e2fsck_run_ext3_journal(e2fsck_t ctx) 3546static int e2fsck_run_ext3_journal(e2fsck_t ctx)
3763{ 3547{
3764 io_manager io_ptr = ctx->fs->io->manager; 3548 io_manager io_ptr = ctx->fs->io->manager;
3765 int blocksize = ctx->fs->blocksize; 3549 int blocksize = ctx->fs->blocksize;
@@ -3806,7 +3590,7 @@ int e2fsck_run_ext3_journal(e2fsck_t ctx)
3806static const char * const journal_names[] = { 3590static const char * const journal_names[] = {
3807 ".journal", "journal", ".journal.dat", "journal.dat", 0 }; 3591 ".journal", "journal", ".journal.dat", "journal.dat", 0 };
3808 3592
3809void e2fsck_move_ext3_journal(e2fsck_t ctx) 3593static void e2fsck_move_ext3_journal(e2fsck_t ctx)
3810{ 3594{
3811 struct ext2_super_block *sb = ctx->fs->super; 3595 struct ext2_super_block *sb = ctx->fs->super;
3812 struct problem_context pctx; 3596 struct problem_context pctx;
@@ -3927,13 +3711,6 @@ err_out:
3927/* 3711/*
3928 * message.c --- print e2fsck messages (with compression) 3712 * message.c --- print e2fsck messages (with compression)
3929 * 3713 *
3930 * Copyright 1996, 1997 by Theodore Ts'o
3931 *
3932 * %Begin-Header%
3933 * This file may be redistributed under the terms of the GNU Public
3934 * License.
3935 * %End-Header%
3936 *
3937 * print_e2fsck_message() prints a message to the user, using 3714 * print_e2fsck_message() prints a message to the user, using
3938 * compression techniques and expansions of abbreviations. 3715 * compression techniques and expansions of abbreviations.
3939 * 3716 *
@@ -4013,7 +3790,7 @@ err_out:
4013 * abbreviation of the form '@<i>' is expanded by looking up the index 3790 * abbreviation of the form '@<i>' is expanded by looking up the index
4014 * letter <i> in the table below. 3791 * letter <i> in the table below.
4015 */ 3792 */
4016static const char *abbrevs[] = { 3793static const char * const abbrevs[] = {
4017 N_("aextended attribute"), 3794 N_("aextended attribute"),
4018 N_("Aerror allocating"), 3795 N_("Aerror allocating"),
4019 N_("bblock"), 3796 N_("bblock"),
@@ -4049,7 +3826,7 @@ static const char *abbrevs[] = {
4049 * Give more user friendly names to the "special" inodes. 3826 * Give more user friendly names to the "special" inodes.
4050 */ 3827 */
4051#define num_special_inodes 11 3828#define num_special_inodes 11
4052static const char *special_inode_name[] = 3829static const char * const special_inode_name[] =
4053{ 3830{
4054 N_("<The NULL inode>"), /* 0 */ 3831 N_("<The NULL inode>"), /* 0 */
4055 N_("<The bad blocks inode>"), /* 1 */ 3832 N_("<The bad blocks inode>"), /* 1 */
@@ -4113,16 +3890,19 @@ static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
4113 } 3890 }
4114} 3891}
4115 3892
3893static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
3894 struct problem_context *pctx, int first);
4116/* 3895/*
4117 * This function handles the '@' expansion. We allow recursive 3896 * This function handles the '@' expansion. We allow recursive
4118 * expansion; an @ expression can contain further '@' and '%' 3897 * expansion; an @ expression can contain further '@' and '%'
4119 * expressions. 3898 * expressions.
4120 */ 3899 */
4121static _INLINE_ void expand_at_expression(e2fsck_t ctx, char ch, 3900static void expand_at_expression(e2fsck_t ctx, char ch,
4122 struct problem_context *pctx, 3901 struct problem_context *pctx,
4123 int *first) 3902 int *first)
4124{ 3903{
4125 const char **cpp, *str; 3904 const char * const *cpp;
3905 const char *str;
4126 3906
4127 /* Search for the abbreviation */ 3907 /* Search for the abbreviation */
4128 for (cpp = abbrevs; *cpp; cpp++) { 3908 for (cpp = abbrevs; *cpp; cpp++) {
@@ -4143,7 +3923,7 @@ static _INLINE_ void expand_at_expression(e2fsck_t ctx, char ch,
4143/* 3923/*
4144 * This function expands '%IX' expressions 3924 * This function expands '%IX' expressions
4145 */ 3925 */
4146static _INLINE_ void expand_inode_expression(char ch, 3926static void expand_inode_expression(char ch,
4147 struct problem_context *ctx) 3927 struct problem_context *ctx)
4148{ 3928{
4149 struct ext2_inode *inode; 3929 struct ext2_inode *inode;
@@ -4344,7 +4124,8 @@ static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
4344 } 4124 }
4345} 4125}
4346 4126
4347void print_e2fsck_message(e2fsck_t ctx, const char *msg, 4127
4128static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
4348 struct problem_context *pctx, int first) 4129 struct problem_context *pctx, int first)
4349{ 4130{
4350 ext2_filsys fs = ctx->fs; 4131 ext2_filsys fs = ctx->fs;
@@ -4375,16 +4156,112 @@ void print_e2fsck_message(e2fsck_t ctx, const char *msg,
4375 first = 0; 4156 first = 0;
4376 } 4157 }
4377} 4158}
4159
4160
4161/*
4162 * region.c --- code which manages allocations within a region.
4163 */
4164
4165struct region_el {
4166 region_addr_t start;
4167 region_addr_t end;
4168 struct region_el *next;
4169};
4170
4171struct region_struct {
4172 region_addr_t min;
4173 region_addr_t max;
4174 struct region_el *allocated;
4175};
4176
4177static region_t region_create(region_addr_t min, region_addr_t max)
4178{
4179 region_t region;
4180
4181 region = malloc(sizeof(struct region_struct));
4182 if (!region)
4183 return NULL;
4184 memset(region, 0, sizeof(struct region_struct));
4185 region->min = min;
4186 region->max = max;
4187 return region;
4188}
4189
4190static void region_free(region_t region)
4191{
4192 struct region_el *r, *next;
4193
4194 for (r = region->allocated; r; r = next) {
4195 next = r->next;
4196 free(r);
4197 }
4198 memset(region, 0, sizeof(struct region_struct));
4199 free(region);
4200}
4201
4202static int region_allocate(region_t region, region_addr_t start, int n)
4203{
4204 struct region_el *r, *new_region, *prev, *next;
4205 region_addr_t end;
4206
4207 end = start+n;
4208 if ((start < region->min) || (end > region->max))
4209 return -1;
4210 if (n == 0)
4211 return 1;
4212
4213 /*
4214 * Search through the linked list. If we find that it
4215 * conflicts witih something that's already allocated, return
4216 * 1; if we can find an existing region which we can grow, do
4217 * so. Otherwise, stop when we find the appropriate place
4218 * insert a new region element into the linked list.
4219 */
4220 for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
4221 if (((start >= r->start) && (start < r->end)) ||
4222 ((end > r->start) && (end <= r->end)) ||
4223 ((start <= r->start) && (end >= r->end)))
4224 return 1;
4225 if (end == r->start) {
4226 r->start = start;
4227 return 0;
4228 }
4229 if (start == r->end) {
4230 if ((next = r->next)) {
4231 if (end > next->start)
4232 return 1;
4233 if (end == next->start) {
4234 r->end = next->end;
4235 r->next = next->next;
4236 free(next);
4237 return 0;
4238 }
4239 }
4240 r->end = end;
4241 return 0;
4242 }
4243 if (start < r->start)
4244 break;
4245 }
4246 /*
4247 * Insert a new region element structure into the linked list
4248 */
4249 new_region = malloc(sizeof(struct region_el));
4250 if (!new_region)
4251 return -1;
4252 new_region->start = start;
4253 new_region->end = start + n;
4254 new_region->next = r;
4255 if (prev)
4256 prev->next = new_region;
4257 else
4258 region->allocated = new_region;
4259 return 0;
4260}
4261
4378/* 4262/*
4379 * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table 4263 * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
4380 * 4264 *
4381 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
4382 *
4383 * %Begin-Header%
4384 * This file may be redistributed under the terms of the GNU Public
4385 * License.
4386 * %End-Header%
4387 *
4388 * Pass 1 of e2fsck iterates over all the inodes in the filesystems, 4265 * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
4389 * and applies the following tests to each inode: 4266 * and applies the following tests to each inode:
4390 * 4267 *
@@ -4478,7 +4355,7 @@ static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
4478 * Free all memory allocated by pass1 in preparation for restarting 4355 * Free all memory allocated by pass1 in preparation for restarting
4479 * things. 4356 * things.
4480 */ 4357 */
4481static void unwind_pass1(ext2_filsys fs EXT2FS_ATTR((unused))) 4358static void unwind_pass1(void)
4482{ 4359{
4483 ext2fs_free_mem(&inodes_to_process); 4360 ext2fs_free_mem(&inodes_to_process);
4484 inodes_to_process = 0; 4361 inodes_to_process = 0;
@@ -4492,7 +4369,8 @@ static void unwind_pass1(ext2_filsys fs EXT2FS_ATTR((unused)))
4492 * since they have the same requirement; the i_block fields should be 4369 * since they have the same requirement; the i_block fields should be
4493 * zero. 4370 * zero.
4494 */ 4371 */
4495int e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode) 4372static int
4373e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
4496{ 4374{
4497 int i; 4375 int i;
4498 4376
@@ -4527,8 +4405,8 @@ int e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
4527 * Check to make sure a symlink inode is real. Returns 1 if the symlink 4405 * Check to make sure a symlink inode is real. Returns 1 if the symlink
4528 * checks out, 0 if not. 4406 * checks out, 0 if not.
4529 */ 4407 */
4530int e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, 4408static int
4531 char *buf) 4409e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
4532{ 4410{
4533 unsigned int len; 4411 unsigned int len;
4534 int i; 4412 int i;
@@ -4737,7 +4615,7 @@ static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
4737 } 4615 }
4738} 4616}
4739 4617
4740void e2fsck_pass1(e2fsck_t ctx) 4618static void e2fsck_pass1(e2fsck_t ctx)
4741{ 4619{
4742 int i; 4620 int i;
4743 __u64 max_sizes; 4621 __u64 max_sizes;
@@ -5250,7 +5128,7 @@ void e2fsck_pass1(e2fsck_t ctx)
5250 * master superblock. 5128 * master superblock.
5251 */ 5129 */
5252 ctx->use_superblock = 0; 5130 ctx->use_superblock = 0;
5253 unwind_pass1(fs); 5131 unwind_pass1();
5254 goto endit; 5132 goto endit;
5255 } 5133 }
5256 5134
@@ -6480,6 +6358,7 @@ void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
6480 fs->write_inode = 0; 6358 fs->write_inode = 0;
6481 } 6359 }
6482} 6360}
6361
6483/* 6362/*
6484 * pass1b.c --- Pass #1b of e2fsck 6363 * pass1b.c --- Pass #1b of e2fsck
6485 * 6364 *
@@ -6500,13 +6379,6 @@ void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
6500 * (so that the file gets a fresh copy of the duplicated blocks) or 6379 * (so that the file gets a fresh copy of the duplicated blocks) or
6501 * simply to delete the file. 6380 * simply to delete the file.
6502 * 6381 *
6503 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
6504 *
6505 * %Begin-Header%
6506 * This file may be redistributed under the terms of the GNU Public
6507 * License.
6508 * %End-Header%
6509 *
6510 */ 6382 */
6511 6383
6512 6384
@@ -6627,8 +6499,7 @@ static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
6627/* 6499/*
6628 * Free a duplicate inode record 6500 * Free a duplicate inode record
6629 */ 6501 */
6630static void inode_dnode_free(dnode_t *node, 6502static void inode_dnode_free(dnode_t *node)
6631 void *context EXT2FS_ATTR((unused)))
6632{ 6503{
6633 struct dup_inode *di; 6504 struct dup_inode *di;
6634 struct block_el *p, *next; 6505 struct block_el *p, *next;
@@ -6644,8 +6515,7 @@ static void inode_dnode_free(dnode_t *node,
6644/* 6515/*
6645 * Free a duplicate block record 6516 * Free a duplicate block record
6646 */ 6517 */
6647static void block_dnode_free(dnode_t *node, 6518static void block_dnode_free(dnode_t *node)
6648 void *context EXT2FS_ATTR((unused)))
6649{ 6519{
6650 struct dup_block *db; 6520 struct dup_block *db;
6651 struct inode_el *p, *next; 6521 struct inode_el *p, *next;
@@ -6679,8 +6549,8 @@ void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
6679 6549
6680 dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp); 6550 dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6681 dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp); 6551 dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6682 dict_set_allocator(&ino_dict, NULL, inode_dnode_free, NULL); 6552 dict_set_allocator(&ino_dict, inode_dnode_free);
6683 dict_set_allocator(&blk_dict, NULL, block_dnode_free, NULL); 6553 dict_set_allocator(&blk_dict, block_dnode_free);
6684 6554
6685 pass1b(ctx, block_buf); 6555 pass1b(ctx, block_buf);
6686 pass1c(ctx, block_buf); 6556 pass1c(ctx, block_buf);
@@ -7275,13 +7145,6 @@ static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
7275/* 7145/*
7276 * pass2.c --- check directory structure 7146 * pass2.c --- check directory structure
7277 * 7147 *
7278 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o
7279 *
7280 * %Begin-Header%
7281 * This file may be redistributed under the terms of the GNU Public
7282 * License.
7283 * %End-Header%
7284 *
7285 * Pass 2 of e2fsck iterates through all active directory inodes, and 7148 * Pass 2 of e2fsck iterates through all active directory inodes, and
7286 * applies to following tests to each directory entry in the directory 7149 * applies to following tests to each directory entry in the directory
7287 * blocks in the inodes: 7150 * blocks in the inodes:
@@ -7324,9 +7187,8 @@ static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
7324static int check_dir_block(ext2_filsys fs, 7187static int check_dir_block(ext2_filsys fs,
7325 struct ext2_db_entry *dir_blocks_info, 7188 struct ext2_db_entry *dir_blocks_info,
7326 void *priv_data); 7189 void *priv_data);
7327static int allocate_dir_block(e2fsck_t ctx, 7190static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
7328 struct ext2_db_entry *dir_blocks_info, 7191 struct problem_context *pctx);
7329 char *buf, struct problem_context *pctx);
7330static int update_dir_block(ext2_filsys fs, 7192static int update_dir_block(ext2_filsys fs,
7331 blk_t *block_nr, 7193 blk_t *block_nr,
7332 e2_blkcnt_t blockcnt, 7194 e2_blkcnt_t blockcnt,
@@ -7345,7 +7207,7 @@ struct check_dir_struct {
7345 e2fsck_t ctx; 7207 e2fsck_t ctx;
7346}; 7208};
7347 7209
7348void e2fsck_pass2(e2fsck_t ctx) 7210static void e2fsck_pass2(e2fsck_t ctx)
7349{ 7211{
7350 struct ext2_super_block *sb = ctx->fs->super; 7212 struct ext2_super_block *sb = ctx->fs->super;
7351 struct problem_context pctx; 7213 struct problem_context pctx;
@@ -7714,7 +7576,6 @@ static int check_dotdot(e2fsck_t ctx,
7714 */ 7576 */
7715static int check_name(e2fsck_t ctx, 7577static int check_name(e2fsck_t ctx,
7716 struct ext2_dir_entry *dirent, 7578 struct ext2_dir_entry *dirent,
7717 ext2_ino_t dir_ino EXT2FS_ATTR((unused)),
7718 struct problem_context *pctx) 7579 struct problem_context *pctx)
7719{ 7580{
7720 int i; 7581 int i;
@@ -7738,9 +7599,38 @@ static int check_name(e2fsck_t ctx,
7738/* 7599/*
7739 * Check the directory filetype (if present) 7600 * Check the directory filetype (if present)
7740 */ 7601 */
7602
7603/*
7604 * Given a mode, return the ext2 file type
7605 */
7606static int ext2_file_type(unsigned int mode)
7607{
7608 if (LINUX_S_ISREG(mode))
7609 return EXT2_FT_REG_FILE;
7610
7611 if (LINUX_S_ISDIR(mode))
7612 return EXT2_FT_DIR;
7613
7614 if (LINUX_S_ISCHR(mode))
7615 return EXT2_FT_CHRDEV;
7616
7617 if (LINUX_S_ISBLK(mode))
7618 return EXT2_FT_BLKDEV;
7619
7620 if (LINUX_S_ISLNK(mode))
7621 return EXT2_FT_SYMLINK;
7622
7623 if (LINUX_S_ISFIFO(mode))
7624 return EXT2_FT_FIFO;
7625
7626 if (LINUX_S_ISSOCK(mode))
7627 return EXT2_FT_SOCK;
7628
7629 return 0;
7630}
7631
7741static _INLINE_ int check_filetype(e2fsck_t ctx, 7632static _INLINE_ int check_filetype(e2fsck_t ctx,
7742 struct ext2_dir_entry *dirent, 7633 struct ext2_dir_entry *dirent,
7743 ext2_ino_t dir_ino EXT2FS_ATTR((unused)),
7744 struct problem_context *pctx) 7634 struct problem_context *pctx)
7745{ 7635{
7746 int filetype = dirent->name_len >> 8; 7636 int filetype = dirent->name_len >> 8;
@@ -8006,7 +7896,7 @@ static int check_dir_block(ext2_filsys fs,
8006 cd->pctx.num = 0; 7896 cd->pctx.num = 0;
8007 7897
8008 if (db->blk == 0) { 7898 if (db->blk == 0) {
8009 if (allocate_dir_block(ctx, db, buf, &cd->pctx)) 7899 if (allocate_dir_block(ctx, db, &cd->pctx))
8010 return 0; 7900 return 0;
8011 block_nr = db->blk; 7901 block_nr = db->blk;
8012 } 7902 }
@@ -8210,10 +8100,10 @@ static int check_dir_block(ext2_filsys fs,
8210 return DIRENT_ABORT; 8100 return DIRENT_ABORT;
8211 } 8101 }
8212 8102
8213 if (check_name(ctx, dirent, ino, &cd->pctx)) 8103 if (check_name(ctx, dirent, &cd->pctx))
8214 dir_modified++; 8104 dir_modified++;
8215 8105
8216 if (check_filetype(ctx, dirent, ino, &cd->pctx)) 8106 if (check_filetype(ctx, dirent, &cd->pctx))
8217 dir_modified++; 8107 dir_modified++;
8218 8108
8219#ifdef ENABLE_HTREE 8109#ifdef ENABLE_HTREE
@@ -8326,8 +8216,7 @@ abort_free_dict:
8326 * This function is called to deallocate a block, and is an interator 8216 * This function is called to deallocate a block, and is an interator
8327 * functioned called by deallocate inode via ext2fs_iterate_block(). 8217 * functioned called by deallocate inode via ext2fs_iterate_block().
8328 */ 8218 */
8329static int deallocate_inode_block(ext2_filsys fs, 8219static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
8330 blk_t *block_nr,
8331 e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), 8220 e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
8332 blk_t ref_block EXT2FS_ATTR((unused)), 8221 blk_t ref_block EXT2FS_ATTR((unused)),
8333 int ref_offset EXT2FS_ATTR((unused)), 8222 int ref_offset EXT2FS_ATTR((unused)),
@@ -8575,9 +8464,7 @@ static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
8575 * a "hole" in it, or if a directory has a illegal block number 8464 * a "hole" in it, or if a directory has a illegal block number
8576 * that was zeroed out and now needs to be replaced. 8465 * that was zeroed out and now needs to be replaced.
8577 */ 8466 */
8578static int allocate_dir_block(e2fsck_t ctx, 8467static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
8579 struct ext2_db_entry *db,
8580 char *buf EXT2FS_ATTR((unused)),
8581 struct problem_context *pctx) 8468 struct problem_context *pctx)
8582{ 8469{
8583 ext2_filsys fs = ctx->fs; 8470 ext2_filsys fs = ctx->fs;
@@ -8673,16 +8560,10 @@ static int update_dir_block(ext2_filsys fs EXT2FS_ATTR((unused)),
8673 } 8560 }
8674 return 0; 8561 return 0;
8675} 8562}
8563
8676/* 8564/*
8677 * pass3.c -- pass #3 of e2fsck: Check for directory connectivity 8565 * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
8678 * 8566 *
8679 * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 Theodore Ts'o.
8680 *
8681 * %Begin-Header%
8682 * This file may be redistributed under the terms of the GNU Public
8683 * License.
8684 * %End-Header%
8685 *
8686 * Pass #3 assures that all directories are connected to the 8567 * Pass #3 assures that all directories are connected to the
8687 * filesystem tree, using the following algorithm: 8568 * filesystem tree, using the following algorithm:
8688 * 8569 *
@@ -8714,10 +8595,10 @@ static int check_directory(e2fsck_t ctx, struct dir_info *dir,
8714 struct problem_context *pctx); 8595 struct problem_context *pctx);
8715static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent); 8596static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
8716 8597
8717static ext2fs_inode_bitmap inode_loop_detect = 0; 8598static ext2fs_inode_bitmap inode_loop_detect;
8718static ext2fs_inode_bitmap inode_done_map = 0; 8599static ext2fs_inode_bitmap inode_done_map;
8719 8600
8720void e2fsck_pass3(e2fsck_t ctx) 8601static void e2fsck_pass3(e2fsck_t ctx)
8721{ 8602{
8722 ext2_filsys fs = ctx->fs; 8603 ext2_filsys fs = ctx->fs;
8723 int i; 8604 int i;
@@ -9473,13 +9354,6 @@ errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
9473/* 9354/*
9474 * pass4.c -- pass #4 of e2fsck: Check reference counts 9355 * pass4.c -- pass #4 of e2fsck: Check reference counts
9475 * 9356 *
9476 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
9477 *
9478 * %Begin-Header%
9479 * This file may be redistributed under the terms of the GNU Public
9480 * License.
9481 * %End-Header%
9482 *
9483 * Pass 4 frees the following data structures: 9357 * Pass 4 frees the following data structures:
9484 * - A bitmap of which inodes are in bad blocks. (inode_bb_map) 9358 * - A bitmap of which inodes are in bad blocks. (inode_bb_map)
9485 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map) 9359 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
@@ -9548,7 +9422,7 @@ static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
9548} 9422}
9549 9423
9550 9424
9551void e2fsck_pass4(e2fsck_t ctx) 9425static void e2fsck_pass4(e2fsck_t ctx)
9552{ 9426{
9553 ext2_filsys fs = ctx->fs; 9427 ext2_filsys fs = ctx->fs;
9554 ext2_ino_t i; 9428 ext2_ino_t i;
@@ -9647,75 +9521,8 @@ void e2fsck_pass4(e2fsck_t ctx)
9647 9521
9648/* 9522/*
9649 * pass5.c --- check block and inode bitmaps against on-disk bitmaps 9523 * pass5.c --- check block and inode bitmaps against on-disk bitmaps
9650 *
9651 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
9652 *
9653 * %Begin-Header%
9654 * This file may be redistributed under the terms of the GNU Public
9655 * License.
9656 * %End-Header%
9657 *
9658 */ 9524 */
9659 9525
9660static void check_block_bitmaps(e2fsck_t ctx);
9661static void check_inode_bitmaps(e2fsck_t ctx);
9662static void check_inode_end(e2fsck_t ctx);
9663static void check_block_end(e2fsck_t ctx);
9664
9665void e2fsck_pass5(e2fsck_t ctx)
9666{
9667#ifdef RESOURCE_TRACK
9668 struct resource_track rtrack;
9669#endif
9670 struct problem_context pctx;
9671
9672#ifdef MTRACE
9673 mtrace_print("Pass 5");
9674#endif
9675
9676#ifdef RESOURCE_TRACK
9677 init_resource_track(&rtrack);
9678#endif
9679
9680 clear_problem_context(&pctx);
9681
9682 if (!(ctx->options & E2F_OPT_PREEN))
9683 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
9684
9685 if (ctx->progress)
9686 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
9687 return;
9688
9689 e2fsck_read_bitmaps(ctx);
9690
9691 check_block_bitmaps(ctx);
9692 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9693 return;
9694 check_inode_bitmaps(ctx);
9695 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9696 return;
9697 check_inode_end(ctx);
9698 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9699 return;
9700 check_block_end(ctx);
9701 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9702 return;
9703
9704 ext2fs_free_inode_bitmap(ctx->inode_used_map);
9705 ctx->inode_used_map = 0;
9706 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
9707 ctx->inode_dir_map = 0;
9708 ext2fs_free_block_bitmap(ctx->block_found_map);
9709 ctx->block_found_map = 0;
9710
9711#ifdef RESOURCE_TRACK
9712 if (ctx->options & E2F_OPT_TIME2) {
9713 e2fsck_clear_progbar(ctx);
9714 print_resource_track(_("Pass 5"), &rtrack);
9715 }
9716#endif
9717}
9718
9719#define NO_BLK ((blk_t) -1) 9526#define NO_BLK ((blk_t) -1)
9720 9527
9721static void print_bitmap_problem(e2fsck_t ctx, int problem, 9528static void print_bitmap_problem(e2fsck_t ctx, int problem,
@@ -10187,17 +9994,62 @@ static void check_block_end(e2fsck_t ctx)
10187 } 9994 }
10188} 9995}
10189 9996
9997static void e2fsck_pass5(e2fsck_t ctx)
9998{
9999#ifdef RESOURCE_TRACK
10000 struct resource_track rtrack;
10001#endif
10002 struct problem_context pctx;
10003
10004#ifdef MTRACE
10005 mtrace_print("Pass 5");
10006#endif
10007
10008#ifdef RESOURCE_TRACK
10009 init_resource_track(&rtrack);
10010#endif
10011
10012 clear_problem_context(&pctx);
10013
10014 if (!(ctx->options & E2F_OPT_PREEN))
10015 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
10016
10017 if (ctx->progress)
10018 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
10019 return;
10020
10021 e2fsck_read_bitmaps(ctx);
10022
10023 check_block_bitmaps(ctx);
10024 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
10025 return;
10026 check_inode_bitmaps(ctx);
10027 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
10028 return;
10029 check_inode_end(ctx);
10030 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
10031 return;
10032 check_block_end(ctx);
10033 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
10034 return;
10035
10036 ext2fs_free_inode_bitmap(ctx->inode_used_map);
10037 ctx->inode_used_map = 0;
10038 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
10039 ctx->inode_dir_map = 0;
10040 ext2fs_free_block_bitmap(ctx->block_found_map);
10041 ctx->block_found_map = 0;
10190 10042
10043#ifdef RESOURCE_TRACK
10044 if (ctx->options & E2F_OPT_TIME2) {
10045 e2fsck_clear_progbar(ctx);
10046 print_resource_track(_("Pass 5"), &rtrack);
10047 }
10048#endif
10049}
10191 10050
10192/* 10051/*
10193 * problem.c --- report filesystem problems to the user 10052 * problem.c --- report filesystem problems to the user
10194 *
10195 * Copyright 1996, 1997 by Theodore Ts'o
10196 *
10197 * %Begin-Header%
10198 * This file may be redistributed under the terms of the GNU Public
10199 * License.
10200 * %End-Header%
10201 */ 10053 */
10202 10054
10203#define PR_PREEN_OK 0x000001 /* Don't need to do preenhalt */ 10055#define PR_PREEN_OK 0x000001 /* Don't need to do preenhalt */
@@ -10258,7 +10110,7 @@ struct latch_descr {
10258 * These are the prompts which are used to ask the user if they want 10110 * These are the prompts which are used to ask the user if they want
10259 * to fix a problem. 10111 * to fix a problem.
10260 */ 10112 */
10261static const char *prompt[] = { 10113static const char * const prompt[] = {
10262 N_("(no prompt)"), /* 0 */ 10114 N_("(no prompt)"), /* 0 */
10263 N_("Fix"), /* 1 */ 10115 N_("Fix"), /* 1 */
10264 N_("Clear"), /* 2 */ 10116 N_("Clear"), /* 2 */
@@ -10286,7 +10138,7 @@ static const char *prompt[] = {
10286 * These messages are printed when we are preen mode and we will be 10138 * These messages are printed when we are preen mode and we will be
10287 * automatically fixing the problem. 10139 * automatically fixing the problem.
10288 */ 10140 */
10289static const char *preen_msg[] = { 10141static const char * const preen_msg[] = {
10290 N_("(NONE)"), /* 0 */ 10142 N_("(NONE)"), /* 0 */
10291 N_("FIXED"), /* 1 */ 10143 N_("FIXED"), /* 1 */
10292 N_("CLEARED"), /* 2 */ 10144 N_("CLEARED"), /* 2 */
@@ -11854,19 +11706,11 @@ int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
11854 11706
11855 return answer; 11707 return answer;
11856} 11708}
11709
11857/* 11710/*
11858 * linux/fs/recovery.c 11711 * linux/fs/recovery.c
11859 * 11712 *
11860 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999 11713 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
11861 *
11862 * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
11863 *
11864 * This file is part of the Linux kernel and is made available under
11865 * the terms of the GNU General Public License, version 2, or at your
11866 * option, any later version, incorporated herein by reference.
11867 *
11868 * Journal recovery routines for the generic filesystem journaling code;
11869 * part of the ext2fs journaling system.
11870 */ 11714 */
11871 11715
11872/* 11716/*
@@ -11889,87 +11733,6 @@ static int do_one_pass(journal_t *journal,
11889static int scan_revoke_records(journal_t *, struct buffer_head *, 11733static int scan_revoke_records(journal_t *, struct buffer_head *,
11890 tid_t, struct recovery_info *); 11734 tid_t, struct recovery_info *);
11891 11735
11892#ifdef __KERNEL__
11893
11894/* Release readahead buffers after use */
11895void journal_brelse_array(struct buffer_head *b[], int n)
11896{
11897 while (--n >= 0)
11898 brelse (b[n]);
11899}
11900
11901
11902/*
11903 * When reading from the journal, we are going through the block device
11904 * layer directly and so there is no readahead being done for us. We
11905 * need to implement any readahead ourselves if we want it to happen at
11906 * all. Recovery is basically one long sequential read, so make sure we
11907 * do the IO in reasonably large chunks.
11908 *
11909 * This is not so critical that we need to be enormously clever about
11910 * the readahead size, though. 128K is a purely arbitrary, good-enough
11911 * fixed value.
11912 */
11913
11914#define MAXBUF 8
11915static int do_readahead(journal_t *journal, unsigned int start)
11916{
11917 int err;
11918 unsigned int max, nbufs, next;
11919 unsigned long blocknr;
11920 struct buffer_head *bh;
11921
11922 struct buffer_head * bufs[MAXBUF];
11923
11924 /* Do up to 128K of readahead */
11925 max = start + (128 * 1024 / journal->j_blocksize);
11926 if (max > journal->j_maxlen)
11927 max = journal->j_maxlen;
11928
11929 /* Do the readahead itself. We'll submit MAXBUF buffer_heads at
11930 * a time to the block device IO layer. */
11931
11932 nbufs = 0;
11933
11934 for (next = start; next < max; next++) {
11935 err = journal_bmap(journal, next, &blocknr);
11936
11937 if (err) {
11938 printk (KERN_ERR "JBD: bad block at offset %u\n",
11939 next);
11940 goto failed;
11941 }
11942
11943 bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
11944 if (!bh) {
11945 err = -ENOMEM;
11946 goto failed;
11947 }
11948
11949 if (!buffer_uptodate(bh) && !buffer_locked(bh)) {
11950 bufs[nbufs++] = bh;
11951 if (nbufs == MAXBUF) {
11952 ll_rw_block(READ, nbufs, bufs);
11953 journal_brelse_array(bufs, nbufs);
11954 nbufs = 0;
11955 }
11956 } else
11957 brelse(bh);
11958 }
11959
11960 if (nbufs)
11961 ll_rw_block(READ, nbufs, bufs);
11962 err = 0;
11963
11964failed:
11965 if (nbufs)
11966 journal_brelse_array(bufs, nbufs);
11967 return err;
11968}
11969
11970#endif /* __KERNEL__ */
11971
11972
11973/* 11736/*
11974 * Read a block from the journal 11737 * Read a block from the journal
11975 */ 11738 */
@@ -11993,7 +11756,7 @@ static int jread(struct buffer_head **bhp, journal_t *journal,
11993 return err; 11756 return err;
11994 } 11757 }
11995 11758
11996 bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); 11759 bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
11997 if (!bh) 11760 if (!bh)
11998 return -ENOMEM; 11761 return -ENOMEM;
11999 11762
@@ -12260,7 +12023,7 @@ static int do_one_pass(journal_t *journal,
12260 12023
12261 /* Find a buffer for the new 12024 /* Find a buffer for the new
12262 * data being restored */ 12025 * data being restored */
12263 nbh = __getblk(journal->j_fs_dev, 12026 nbh = getblk(journal->j_fs_dev,
12264 blocknr, 12027 blocknr,
12265 journal->j_blocksize); 12028 journal->j_blocksize);
12266 if (nbh == NULL) { 12029 if (nbh == NULL) {
@@ -12282,7 +12045,7 @@ static int do_one_pass(journal_t *journal,
12282 } 12045 }
12283 12046
12284 BUFFER_TRACE(nbh, "marking dirty"); 12047 BUFFER_TRACE(nbh, "marking dirty");
12285 set_buffer_uptodate(nbh); 12048 mark_buffer_uptodate(nbh, 1);
12286 mark_buffer_dirty(nbh); 12049 mark_buffer_dirty(nbh);
12287 BUFFER_TRACE(nbh, "marking uptodate"); 12050 BUFFER_TRACE(nbh, "marking uptodate");
12288 ++info->nr_replays; 12051 ++info->nr_replays;
@@ -12388,124 +12151,11 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
12388 } 12151 }
12389 return 0; 12152 return 0;
12390} 12153}
12391/*
12392 * region.c --- code which manages allocations within a region.
12393 *
12394 * Copyright (C) 2001 Theodore Ts'o.
12395 *
12396 * %Begin-Header%
12397 * This file may be redistributed under the terms of the GNU Public
12398 * License.
12399 * %End-Header%
12400 */
12401
12402struct region_el {
12403 region_addr_t start;
12404 region_addr_t end;
12405 struct region_el *next;
12406};
12407
12408struct region_struct {
12409 region_addr_t min;
12410 region_addr_t max;
12411 struct region_el *allocated;
12412};
12413
12414region_t region_create(region_addr_t min, region_addr_t max)
12415{
12416 region_t region;
12417
12418 region = malloc(sizeof(struct region_struct));
12419 if (!region)
12420 return NULL;
12421 memset(region, 0, sizeof(struct region_struct));
12422 region->min = min;
12423 region->max = max;
12424 return region;
12425}
12426
12427void region_free(region_t region)
12428{
12429 struct region_el *r, *next;
12430 12154
12431 for (r = region->allocated; r; r = next) {
12432 next = r->next;
12433 free(r);
12434 }
12435 memset(region, 0, sizeof(struct region_struct));
12436 free(region);
12437}
12438
12439int region_allocate(region_t region, region_addr_t start, int n)
12440{
12441 struct region_el *r, *new_region, *prev, *next;
12442 region_addr_t end;
12443
12444 end = start+n;
12445 if ((start < region->min) || (end > region->max))
12446 return -1;
12447 if (n == 0)
12448 return 1;
12449
12450 /*
12451 * Search through the linked list. If we find that it
12452 * conflicts witih something that's already allocated, return
12453 * 1; if we can find an existing region which we can grow, do
12454 * so. Otherwise, stop when we find the appropriate place
12455 * insert a new region element into the linked list.
12456 */
12457 for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
12458 if (((start >= r->start) && (start < r->end)) ||
12459 ((end > r->start) && (end <= r->end)) ||
12460 ((start <= r->start) && (end >= r->end)))
12461 return 1;
12462 if (end == r->start) {
12463 r->start = start;
12464 return 0;
12465 }
12466 if (start == r->end) {
12467 if ((next = r->next)) {
12468 if (end > next->start)
12469 return 1;
12470 if (end == next->start) {
12471 r->end = next->end;
12472 r->next = next->next;
12473 free(next);
12474 return 0;
12475 }
12476 }
12477 r->end = end;
12478 return 0;
12479 }
12480 if (start < r->start)
12481 break;
12482 }
12483 /*
12484 * Insert a new region element structure into the linked list
12485 */
12486 new_region = malloc(sizeof(struct region_el));
12487 if (!new_region)
12488 return -1;
12489 new_region->start = start;
12490 new_region->end = start + n;
12491 new_region->next = r;
12492 if (prev)
12493 prev->next = new_region;
12494 else
12495 region->allocated = new_region;
12496 return 0;
12497}
12498 12155
12499/* 12156/*
12500 * rehash.c --- rebuild hash tree directories 12157 * rehash.c --- rebuild hash tree directories
12501 * 12158 *
12502 * Copyright (C) 2002 Theodore Ts'o
12503 *
12504 * %Begin-Header%
12505 * This file may be redistributed under the terms of the GNU Public
12506 * License.
12507 * %End-Header%
12508 *
12509 * This algorithm is designed for simplicity of implementation and to 12159 * This algorithm is designed for simplicity of implementation and to
12510 * pack the directory as much as possible. It however requires twice 12160 * pack the directory as much as possible. It however requires twice
12511 * as much memory as the size of the directory. The maximum size 12161 * as much memory as the size of the directory. The maximum size
@@ -13146,7 +12796,7 @@ static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
13146 return 0; 12796 return 0;
13147} 12797}
13148 12798
13149errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino) 12799static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
13150{ 12800{
13151 ext2_filsys fs = ctx->fs; 12801 ext2_filsys fs = ctx->fs;
13152 errcode_t retval; 12802 errcode_t retval;
@@ -13330,17 +12980,10 @@ void e2fsck_rehash_directories(e2fsck_t ctx)
13330 } 12980 }
13331#endif 12981#endif
13332} 12982}
12983
13333/* 12984/*
13334 * linux/fs/revoke.c 12985 * linux/fs/revoke.c
13335 * 12986 *
13336 * Written by Stephen C. Tweedie <sct@redhat.com>, 2000
13337 *
13338 * Copyright 2000 Red Hat corp --- All Rights Reserved
13339 *
13340 * This file is part of the Linux kernel and is made available under
13341 * the terms of the GNU General Public License, version 2, or at your
13342 * option, any later version, incorporated herein by reference.
13343 *
13344 * Journal revoke routines for the generic filesystem journaling code; 12987 * Journal revoke routines for the generic filesystem journaling code;
13345 * part of the ext2fs journaling system. 12988 * part of the ext2fs journaling system.
13346 * 12989 *
@@ -13415,13 +13058,6 @@ struct jbd_revoke_table_s
13415}; 13058};
13416 13059
13417 13060
13418#ifdef __KERNEL__
13419static void write_one_revoke_record(journal_t *, transaction_t *,
13420 struct journal_head **, int *,
13421 struct jbd_revoke_record_s *);
13422static void flush_descriptor(journal_t *, struct journal_head *, int);
13423#endif
13424
13425/* Utility functions to maintain the revoke table */ 13061/* Utility functions to maintain the revoke table */
13426 13062
13427/* Borrowed from buffer.c: this is a tried and tested block hash function */ 13063/* Borrowed from buffer.c: this is a tried and tested block hash function */
@@ -13441,9 +13077,6 @@ static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
13441 struct list_head *hash_list; 13077 struct list_head *hash_list;
13442 struct jbd_revoke_record_s *record; 13078 struct jbd_revoke_record_s *record;
13443 13079
13444#ifdef __KERNEL__
13445repeat:
13446#endif
13447 record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS); 13080 record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
13448 if (!record) 13081 if (!record)
13449 goto oom; 13082 goto oom;
@@ -13455,16 +13088,7 @@ repeat:
13455 return 0; 13088 return 0;
13456 13089
13457oom: 13090oom:
13458#ifdef __KERNEL__
13459 if (!journal_oom_retry)
13460 return -ENOMEM;
13461 jbd_debug(1, "ENOMEM in " __FUNCTION__ ", retrying.\n");
13462 current->policy |= SCHED_YIELD;
13463 schedule();
13464 goto repeat;
13465#else
13466 return -ENOMEM; 13091 return -ENOMEM;
13467#endif
13468} 13092}
13469 13093
13470/* Find a revoke record in the journal's hash table. */ 13094/* Find a revoke record in the journal's hash table. */
@@ -13488,17 +13112,13 @@ static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
13488 13112
13489int journal_init_revoke_caches(void) 13113int journal_init_revoke_caches(void)
13490{ 13114{
13491 revoke_record_cache = kmem_cache_create("revoke_record", 13115 revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
13492 sizeof(struct jbd_revoke_record_s),
13493 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
13494 if (revoke_record_cache == 0) 13116 if (revoke_record_cache == 0)
13495 return -ENOMEM; 13117 return -ENOMEM;
13496 13118
13497 revoke_table_cache = kmem_cache_create("revoke_table", 13119 revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
13498 sizeof(struct jbd_revoke_table_s),
13499 0, 0, NULL, NULL);
13500 if (revoke_table_cache == 0) { 13120 if (revoke_table_cache == 0) {
13501 kmem_cache_destroy(revoke_record_cache); 13121 do_cache_destroy(revoke_record_cache);
13502 revoke_record_cache = NULL; 13122 revoke_record_cache = NULL;
13503 return -ENOMEM; 13123 return -ENOMEM;
13504 } 13124 }
@@ -13507,9 +13127,9 @@ int journal_init_revoke_caches(void)
13507 13127
13508void journal_destroy_revoke_caches(void) 13128void journal_destroy_revoke_caches(void)
13509{ 13129{
13510 kmem_cache_destroy(revoke_record_cache); 13130 do_cache_destroy(revoke_record_cache);
13511 revoke_record_cache = 0; 13131 revoke_record_cache = 0;
13512 kmem_cache_destroy(revoke_table_cache); 13132 do_cache_destroy(revoke_table_cache);
13513 revoke_table_cache = 0; 13133 revoke_table_cache = 0;
13514} 13134}
13515 13135
@@ -13536,10 +13156,9 @@ int journal_init_revoke(journal_t *journal, int hash_size)
13536 shift++; 13156 shift++;
13537 journal->j_revoke->hash_shift = shift; 13157 journal->j_revoke->hash_shift = shift;
13538 13158
13539 journal->j_revoke->hash_table = 13159 journal->j_revoke->hash_table = malloc(hash_size * sizeof(struct list_head));
13540 kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL);
13541 if (!journal->j_revoke->hash_table) { 13160 if (!journal->j_revoke->hash_table) {
13542 kmem_cache_free(revoke_table_cache, journal->j_revoke); 13161 free(journal->j_revoke);
13543 journal->j_revoke = NULL; 13162 journal->j_revoke = NULL;
13544 return -ENOMEM; 13163 return -ENOMEM;
13545 } 13164 }
@@ -13567,311 +13186,11 @@ void journal_destroy_revoke(journal_t *journal)
13567 J_ASSERT (list_empty(hash_list)); 13186 J_ASSERT (list_empty(hash_list));
13568 } 13187 }
13569 13188
13570 kfree(table->hash_table); 13189 free(table->hash_table);
13571 kmem_cache_free(revoke_table_cache, table); 13190 free(table);
13572 journal->j_revoke = NULL; 13191 journal->j_revoke = NULL;
13573} 13192}
13574 13193
13575
13576#ifdef __KERNEL__
13577
13578/*
13579 * journal_revoke: revoke a given buffer_head from the journal. This
13580 * prevents the block from being replayed during recovery if we take a
13581 * crash after this current transaction commits. Any subsequent
13582 * metadata writes of the buffer in this transaction cancel the
13583 * revoke.
13584 *
13585 * Note that this call may block --- it is up to the caller to make
13586 * sure that there are no further calls to journal_write_metadata
13587 * before the revoke is complete. In ext3, this implies calling the
13588 * revoke before clearing the block bitmap when we are deleting
13589 * metadata.
13590 *
13591 * Revoke performs a journal_forget on any buffer_head passed in as a
13592 * parameter, but does _not_ forget the buffer_head if the bh was only
13593 * found implicitly.
13594 *
13595 * bh_in may not be a journalled buffer - it may have come off
13596 * the hash tables without an attached journal_head.
13597 *
13598 * If bh_in is non-zero, journal_revoke() will decrement its b_count
13599 * by one.
13600 */
13601
13602int journal_revoke(handle_t *handle, unsigned long blocknr,
13603 struct buffer_head *bh_in)
13604{
13605 struct buffer_head *bh = NULL;
13606 journal_t *journal;
13607 kdev_t dev;
13608 int err;
13609
13610 if (bh_in)
13611 BUFFER_TRACE(bh_in, "enter");
13612
13613 journal = handle->h_transaction->t_journal;
13614 if (!journal_set_features(journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)){
13615 J_ASSERT (!"Cannot set revoke feature!");
13616 return -EINVAL;
13617 }
13618
13619 dev = journal->j_fs_dev;
13620 bh = bh_in;
13621
13622 if (!bh) {
13623 bh = get_hash_table(dev, blocknr, journal->j_blocksize);
13624 if (bh)
13625 BUFFER_TRACE(bh, "found on hash");
13626 }
13627#ifdef JBD_EXPENSIVE_CHECKING
13628 else {
13629 struct buffer_head *bh2;
13630
13631 /* If there is a different buffer_head lying around in
13632 * memory anywhere... */
13633 bh2 = get_hash_table(dev, blocknr, journal->j_blocksize);
13634 if (bh2) {
13635 /* ... and it has RevokeValid status... */
13636 if ((bh2 != bh) &&
13637 test_bit(BH_RevokeValid, &bh2->b_state))
13638 /* ...then it better be revoked too,
13639 * since it's illegal to create a revoke
13640 * record against a buffer_head which is
13641 * not marked revoked --- that would
13642 * risk missing a subsequent revoke
13643 * cancel. */
13644 J_ASSERT_BH(bh2, test_bit(BH_Revoked, &
13645 bh2->b_state));
13646 __brelse(bh2);
13647 }
13648 }
13649#endif
13650
13651 /* We really ought not ever to revoke twice in a row without
13652 first having the revoke cancelled: it's illegal to free a
13653 block twice without allocating it in between! */
13654 if (bh) {
13655 J_ASSERT_BH(bh, !test_bit(BH_Revoked, &bh->b_state));
13656 set_bit(BH_Revoked, &bh->b_state);
13657 set_bit(BH_RevokeValid, &bh->b_state);
13658 if (bh_in) {
13659 BUFFER_TRACE(bh_in, "call journal_forget");
13660 journal_forget(handle, bh_in);
13661 } else {
13662 BUFFER_TRACE(bh, "call brelse");
13663 __brelse(bh);
13664 }
13665 }
13666
13667 lock_journal(journal);
13668 jbd_debug(2, "insert revoke for block %lu, bh_in=%p\n", blocknr, bh_in);
13669 err = insert_revoke_hash(journal, blocknr,
13670 handle->h_transaction->t_tid);
13671 unlock_journal(journal);
13672 BUFFER_TRACE(bh_in, "exit");
13673 return err;
13674}
13675
13676/*
13677 * Cancel an outstanding revoke. For use only internally by the
13678 * journaling code (called from journal_get_write_access).
13679 *
13680 * We trust the BH_Revoked bit on the buffer if the buffer is already
13681 * being journaled: if there is no revoke pending on the buffer, then we
13682 * don't do anything here.
13683 *
13684 * This would break if it were possible for a buffer to be revoked and
13685 * discarded, and then reallocated within the same transaction. In such
13686 * a case we would have lost the revoked bit, but when we arrived here
13687 * the second time we would still have a pending revoke to cancel. So,
13688 * do not trust the Revoked bit on buffers unless RevokeValid is also
13689 * set.
13690 *
13691 * The caller must have the journal locked.
13692 */
13693int journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
13694{
13695 struct jbd_revoke_record_s *record;
13696 journal_t *journal = handle->h_transaction->t_journal;
13697 int need_cancel;
13698 int did_revoke = 0; /* akpm: debug */
13699 struct buffer_head *bh = jh2bh(jh);
13700
13701 jbd_debug(4, "journal_head %p, cancelling revoke\n", jh);
13702
13703 /* Is the existing Revoke bit valid? If so, we trust it, and
13704 * only perform the full cancel if the revoke bit is set. If
13705 * not, we can't trust the revoke bit, and we need to do the
13706 * full search for a revoke record. */
13707 if (test_and_set_bit(BH_RevokeValid, &bh->b_state))
13708 need_cancel = (test_and_clear_bit(BH_Revoked, &bh->b_state));
13709 else {
13710 need_cancel = 1;
13711 clear_bit(BH_Revoked, &bh->b_state);
13712 }
13713
13714 if (need_cancel) {
13715 record = find_revoke_record(journal, bh->b_blocknr);
13716 if (record) {
13717 jbd_debug(4, "cancelled existing revoke on "
13718 "blocknr %lu\n", bh->b_blocknr);
13719 list_del(&record->hash);
13720 kmem_cache_free(revoke_record_cache, record);
13721 did_revoke = 1;
13722 }
13723 }
13724
13725#ifdef JBD_EXPENSIVE_CHECKING
13726 /* There better not be one left behind by now! */
13727 record = find_revoke_record(journal, bh->b_blocknr);
13728 J_ASSERT_JH(jh, record == NULL);
13729#endif
13730
13731 /* Finally, have we just cleared revoke on an unhashed
13732 * buffer_head? If so, we'd better make sure we clear the
13733 * revoked status on any hashed alias too, otherwise the revoke
13734 * state machine will get very upset later on. */
13735 if (need_cancel && !bh->b_pprev) {
13736 struct buffer_head *bh2;
13737 bh2 = get_hash_table(bh->b_dev, bh->b_blocknr, bh->b_size);
13738 if (bh2) {
13739 clear_bit(BH_Revoked, &bh2->b_state);
13740 __brelse(bh2);
13741 }
13742 }
13743
13744 return did_revoke;
13745}
13746
13747
13748/*
13749 * Write revoke records to the journal for all entries in the current
13750 * revoke hash, deleting the entries as we go.
13751 *
13752 * Called with the journal lock held.
13753 */
13754
13755void journal_write_revoke_records(journal_t *journal,
13756 transaction_t *transaction)
13757{
13758 struct journal_head *descriptor;
13759 struct jbd_revoke_record_s *record;
13760 struct jbd_revoke_table_s *revoke;
13761 struct list_head *hash_list;
13762 int i, offset, count;
13763
13764 descriptor = NULL;
13765 offset = 0;
13766 count = 0;
13767 revoke = journal->j_revoke;
13768
13769 for (i = 0; i < revoke->hash_size; i++) {
13770 hash_list = &revoke->hash_table[i];
13771
13772 while (!list_empty(hash_list)) {
13773 record = (struct jbd_revoke_record_s *)
13774 hash_list->next;
13775 write_one_revoke_record(journal, transaction,
13776 &descriptor, &offset,
13777 record);
13778 count++;
13779 list_del(&record->hash);
13780 kmem_cache_free(revoke_record_cache, record);
13781 }
13782 }
13783 if (descriptor)
13784 flush_descriptor(journal, descriptor, offset);
13785 jbd_debug(1, "Wrote %d revoke records\n", count);
13786}
13787
13788/*
13789 * Write out one revoke record. We need to create a new descriptor
13790 * block if the old one is full or if we have not already created one.
13791 */
13792
13793static void write_one_revoke_record(journal_t *journal,
13794 transaction_t *transaction,
13795 struct journal_head **descriptorp,
13796 int *offsetp,
13797 struct jbd_revoke_record_s *record)
13798{
13799 struct journal_head *descriptor;
13800 int offset;
13801 journal_header_t *header;
13802
13803 /* If we are already aborting, this all becomes a noop. We
13804 still need to go round the loop in
13805 journal_write_revoke_records in order to free all of the
13806 revoke records: only the IO to the journal is omitted. */
13807 if (is_journal_aborted(journal))
13808 return;
13809
13810 descriptor = *descriptorp;
13811 offset = *offsetp;
13812
13813 /* Make sure we have a descriptor with space left for the record */
13814 if (descriptor) {
13815 if (offset == journal->j_blocksize) {
13816 flush_descriptor(journal, descriptor, offset);
13817 descriptor = NULL;
13818 }
13819 }
13820
13821 if (!descriptor) {
13822 descriptor = journal_get_descriptor_buffer(journal);
13823 if (!descriptor)
13824 return;
13825 header = (journal_header_t *) &jh2bh(descriptor)->b_data[0];
13826 header->h_magic = htonl(JFS_MAGIC_NUMBER);
13827 header->h_blocktype = htonl(JFS_REVOKE_BLOCK);
13828 header->h_sequence = htonl(transaction->t_tid);
13829
13830 /* Record it so that we can wait for IO completion later */
13831 JBUFFER_TRACE(descriptor, "file as BJ_LogCtl");
13832 journal_file_buffer(descriptor, transaction, BJ_LogCtl);
13833
13834 offset = sizeof(journal_revoke_header_t);
13835 *descriptorp = descriptor;
13836 }
13837
13838 * ((unsigned int *)(&jh2bh(descriptor)->b_data[offset])) =
13839 htonl(record->blocknr);
13840 offset += 4;
13841 *offsetp = offset;
13842}
13843
13844/*
13845 * Flush a revoke descriptor out to the journal. If we are aborting,
13846 * this is a noop; otherwise we are generating a buffer which needs to
13847 * be waited for during commit, so it has to go onto the appropriate
13848 * journal buffer list.
13849 */
13850
13851static void flush_descriptor(journal_t *journal,
13852 struct journal_head *descriptor,
13853 int offset)
13854{
13855 journal_revoke_header_t *header;
13856
13857 if (is_journal_aborted(journal)) {
13858 JBUFFER_TRACE(descriptor, "brelse");
13859 __brelse(jh2bh(descriptor));
13860 return;
13861 }
13862
13863 header = (journal_revoke_header_t *) jh2bh(descriptor)->b_data;
13864 header->r_count = htonl(offset);
13865 set_bit(BH_JWrite, &jh2bh(descriptor)->b_state);
13866 {
13867 struct buffer_head *bh = jh2bh(descriptor);
13868 BUFFER_TRACE(bh, "write");
13869 ll_rw_block (WRITE, 1, &bh);
13870 }
13871}
13872
13873#endif
13874
13875/* 13194/*
13876 * Revoke support for recovery. 13195 * Revoke support for recovery.
13877 * 13196 *
@@ -13894,8 +13213,7 @@ static void flush_descriptor(journal_t *journal,
13894 * single block. 13213 * single block.
13895 */ 13214 */
13896 13215
13897int journal_set_revoke(journal_t *journal, 13216int journal_set_revoke(journal_t *journal, unsigned long blocknr,
13898 unsigned long blocknr,
13899 tid_t sequence) 13217 tid_t sequence)
13900{ 13218{
13901 struct jbd_revoke_record_s *record; 13219 struct jbd_revoke_record_s *record;
@@ -13918,8 +13236,7 @@ int journal_set_revoke(journal_t *journal,
13918 * ones, but later transactions still need replayed. 13236 * ones, but later transactions still need replayed.
13919 */ 13237 */
13920 13238
13921int journal_test_revoke(journal_t *journal, 13239int journal_test_revoke(journal_t *journal, unsigned long blocknr,
13922 unsigned long blocknr,
13923 tid_t sequence) 13240 tid_t sequence)
13924{ 13241{
13925 struct jbd_revoke_record_s *record; 13242 struct jbd_revoke_record_s *record;
@@ -13951,20 +13268,13 @@ void journal_clear_revoke(journal_t *journal)
13951 while (!list_empty(hash_list)) { 13268 while (!list_empty(hash_list)) {
13952 record = (struct jbd_revoke_record_s*) hash_list->next; 13269 record = (struct jbd_revoke_record_s*) hash_list->next;
13953 list_del(&record->hash); 13270 list_del(&record->hash);
13954 kmem_cache_free(revoke_record_cache, record); 13271 free(record);
13955 } 13272 }
13956 } 13273 }
13957} 13274}
13958 13275
13959/* 13276/*
13960 * e2fsck.c - superblock checks 13277 * e2fsck.c - superblock checks
13961 *
13962 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
13963 *
13964 * %Begin-Header%
13965 * This file may be redistributed under the terms of the GNU Public
13966 * License.
13967 * %End-Header%
13968 */ 13278 */
13969 13279
13970#define MIN_CHECK 1 13280#define MIN_CHECK 1
@@ -13991,7 +13301,7 @@ static void check_super_value(e2fsck_t ctx, const char *descr,
13991 * e2fsck code.. 13301 * e2fsck code..
13992 */ 13302 */
13993#ifndef EXT2_SPECIAL_DEVICE_SIZE 13303#ifndef EXT2_SPECIAL_DEVICE_SIZE
13994errcode_t e2fsck_get_device_size(e2fsck_t ctx) 13304static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
13995{ 13305{
13996 return (ext2fs_get_device_size(ctx->filesystem_name, 13306 return (ext2fs_get_device_size(ctx->filesystem_name,
13997 EXT2_BLOCK_SIZE(ctx->fs->super), 13307 EXT2_BLOCK_SIZE(ctx->fs->super),
@@ -14014,8 +13324,7 @@ struct process_block_struct {
14014 errcode_t errcode; 13324 errcode_t errcode;
14015}; 13325};
14016 13326
14017static int release_inode_block(ext2_filsys fs, 13327static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
14018 blk_t *block_nr,
14019 e2_blkcnt_t blockcnt, 13328 e2_blkcnt_t blockcnt,
14020 blk_t ref_blk EXT2FS_ATTR((unused)), 13329 blk_t ref_blk EXT2FS_ATTR((unused)),
14021 int ref_offset EXT2FS_ATTR((unused)), 13330 int ref_offset EXT2FS_ATTR((unused)),
@@ -14384,7 +13693,7 @@ cleanup:
14384 13693
14385 } 13694 }
14386 13695
14387void check_super_block(e2fsck_t ctx) 13696static void check_super_block(e2fsck_t ctx)
14388{ 13697{
14389 ext2_filsys fs = ctx->fs; 13698 ext2_filsys fs = ctx->fs;
14390 blk_t first_block, last_block; 13699 blk_t first_block, last_block;
@@ -14659,16 +13968,9 @@ void check_super_block(e2fsck_t ctx)
14659 e2fsck_move_ext3_journal(ctx); 13968 e2fsck_move_ext3_journal(ctx);
14660 return; 13969 return;
14661} 13970}
13971
14662/* 13972/*
14663 * swapfs.c --- byte-swap an ext2 filesystem 13973 * swapfs.c --- byte-swap an ext2 filesystem
14664 *
14665 * Copyright 1996, 1997 by Theodore Ts'o
14666 *
14667 * %Begin-Header%
14668 * This file may be redistributed under the terms of the GNU Public
14669 * License.
14670 * %End-Header%
14671 *
14672 */ 13974 */
14673 13975
14674#ifdef ENABLE_SWAPFS 13976#ifdef ENABLE_SWAPFS
@@ -14866,7 +14168,7 @@ static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
14866 14168
14867 14169
14868#ifdef ENABLE_SWAPFS 14170#ifdef ENABLE_SWAPFS
14869void swap_filesys(e2fsck_t ctx) 14171static void swap_filesys(e2fsck_t ctx)
14870{ 14172{
14871 ext2_filsys fs = ctx->fs; 14173 ext2_filsys fs = ctx->fs;
14872#ifdef RESOURCE_TRACK 14174#ifdef RESOURCE_TRACK
@@ -14924,15 +14226,9 @@ void swap_filesys(e2fsck_t ctx)
14924#endif /* ENABLE_SWAPFS */ 14226#endif /* ENABLE_SWAPFS */
14925 14227
14926#endif 14228#endif
14229
14927/* 14230/*
14928 * util.c --- miscellaneous utilities 14231 * util.c --- miscellaneous utilities
14929 *
14930 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
14931 *
14932 * %Begin-Header%
14933 * This file may be redistributed under the terms of the GNU Public
14934 * License.
14935 * %End-Header%
14936 */ 14232 */
14937 14233
14938#ifdef HAVE_CONIO_H 14234#ifdef HAVE_CONIO_H
@@ -14981,8 +14277,7 @@ void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
14981 return ret; 14277 return ret;
14982} 14278}
14983 14279
14984char *string_copy(e2fsck_t ctx EXT2FS_ATTR((unused)), 14280static char *string_copy(const char *str, int len)
14985 const char *str, int len)
14986{ 14281{
14987 char *ret; 14282 char *ret;
14988 14283
@@ -15020,12 +14315,12 @@ static int read_a_char(void)
15020} 14315}
15021#endif 14316#endif
15022 14317
15023int ask_yn(const char * string, int def) 14318static int ask_yn(const char * string, int def)
15024{ 14319{
15025 int c; 14320 int c;
15026 const char *defstr; 14321 const char *defstr;
15027 const char *short_yes = _("yY"); 14322 static const char short_yes[] = "yY";
15028 const char *short_no = _("nN"); 14323 static const char short_no[] = "nN";
15029 14324
15030#ifdef HAVE_TERMIOS_H 14325#ifdef HAVE_TERMIOS_H
15031 struct termios termios, tmp; 14326 struct termios termios, tmp;
@@ -15039,11 +14334,11 @@ int ask_yn(const char * string, int def)
15039#endif 14334#endif
15040 14335
15041 if (def == 1) 14336 if (def == 1)
15042 defstr = _(_("<y>")); 14337 defstr = "<y>";
15043 else if (def == 0) 14338 else if (def == 0)
15044 defstr = _(_("<n>")); 14339 defstr = "<n>";
15045 else 14340 else
15046 defstr = _(" (y/n)"); 14341 defstr = " (y/n)";
15047 printf("%s%s? ", string, defstr); 14342 printf("%s%s? ", string, defstr);
15048 while (1) { 14343 while (1) {
15049 fflush (stdout); 14344 fflush (stdout);
@@ -15073,9 +14368,9 @@ int ask_yn(const char * string, int def)
15073 break; 14368 break;
15074 } 14369 }
15075 if (def) 14370 if (def)
15076 puts(_("yes\n")); 14371 puts("yes\n");
15077 else 14372 else
15078 puts (_("no\n")); 14373 puts ("no\n");
15079#ifdef HAVE_TERMIOS_H 14374#ifdef HAVE_TERMIOS_H
15080 tcsetattr (0, TCSANOW, &termios); 14375 tcsetattr (0, TCSANOW, &termios);
15081#endif 14376#endif
@@ -15122,7 +14417,7 @@ void e2fsck_read_bitmaps(e2fsck_t ctx)
15122 } 14417 }
15123} 14418}
15124 14419
15125void e2fsck_write_bitmaps(e2fsck_t ctx) 14420static void e2fsck_write_bitmaps(e2fsck_t ctx)
15126{ 14421{
15127 ext2_filsys fs = ctx->fs; 14422 ext2_filsys fs = ctx->fs;
15128 errcode_t retval; 14423 errcode_t retval;
@@ -15361,47 +14656,50 @@ cleanup:
15361 return (ret_sb); 14656 return (ret_sb);
15362} 14657}
15363 14658
14659
15364/* 14660/*
15365 * Given a mode, return the ext2 file type 14661 * This function runs through the e2fsck passes and calls them all,
14662 * returning restart, abort, or cancel as necessary...
15366 */ 14663 */
15367int ext2_file_type(unsigned int mode) 14664typedef void (*pass_t)(e2fsck_t ctx);
15368{
15369 if (LINUX_S_ISREG(mode))
15370 return EXT2_FT_REG_FILE;
15371
15372 if (LINUX_S_ISDIR(mode))
15373 return EXT2_FT_DIR;
15374 14665
15375 if (LINUX_S_ISCHR(mode)) 14666static const pass_t e2fsck_passes[] = {
15376 return EXT2_FT_CHRDEV; 14667 e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
14668 e2fsck_pass5, 0 };
15377 14669
15378 if (LINUX_S_ISBLK(mode)) 14670#define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
15379 return EXT2_FT_BLKDEV;
15380 14671
15381 if (LINUX_S_ISLNK(mode)) 14672static int e2fsck_run(e2fsck_t ctx)
15382 return EXT2_FT_SYMLINK; 14673{
14674 int i;
14675 pass_t e2fsck_pass;
15383 14676
15384 if (LINUX_S_ISFIFO(mode)) 14677 if (setjmp(ctx->abort_loc)) {
15385 return EXT2_FT_FIFO; 14678 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
14679 return (ctx->flags & E2F_FLAG_RUN_RETURN);
14680 }
14681 ctx->flags |= E2F_FLAG_SETJMP_OK;
15386 14682
15387 if (LINUX_S_ISSOCK(mode)) 14683 for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
15388 return EXT2_FT_SOCK; 14684 if (ctx->flags & E2F_FLAG_RUN_RETURN)
14685 break;
14686 e2fsck_pass(ctx);
14687 if (ctx->progress)
14688 (void) (ctx->progress)(ctx, 0, 0, 0);
14689 }
14690 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
15389 14691
14692 if (ctx->flags & E2F_FLAG_RUN_RETURN)
14693 return (ctx->flags & E2F_FLAG_RUN_RETURN);
15390 return 0; 14694 return 0;
15391} 14695}
14696
14697
15392/* 14698/*
15393 * unix.c - The unix-specific code for e2fsck 14699 * unix.c - The unix-specific code for e2fsck
15394 *
15395 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
15396 *
15397 * %Begin-Header%
15398 * This file may be redistributed under the terms of the GNU Public
15399 * License.
15400 * %End-Header%
15401 */ 14700 */
15402 14701
15403 14702
15404
15405/* Command line options */ 14703/* Command line options */
15406static int swapfs; 14704static int swapfs;
15407#ifdef ENABLE_SWAPFS 14705#ifdef ENABLE_SWAPFS
@@ -15448,6 +14746,8 @@ static void usage(e2fsck_t ctx)
15448} 14746}
15449#endif 14747#endif
15450 14748
14749#define P_E2(singular, plural, n) n, ((n) == 1 ? singular : plural)
14750
15451static void show_stats(e2fsck_t ctx) 14751static void show_stats(e2fsck_t ctx)
15452{ 14752{
15453 ext2_filsys fs = ctx->fs; 14753 ext2_filsys fs = ctx->fs;
@@ -15476,45 +14776,27 @@ static void show_stats(e2fsck_t ctx)
15476 blocks_used, blocks); 14776 blocks_used, blocks);
15477 return; 14777 return;
15478 } 14778 }
15479 printf (P_("\n%8d inode used (%d%%)\n", "\n%8d inodes used (%d%%)\n", 14779 printf ("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
15480 inodes_used), inodes_used, 100 * inodes_used / inodes); 14780 100 * inodes_used / inodes);
15481 printf (P_("%8d non-contiguous inode (%0d.%d%%)\n", 14781 printf ("%8d non-contiguous inode%s (%0d.%d%%)\n",
15482 "%8d non-contiguous inodes (%0d.%d%%)\n", 14782 P_E2("", "s", ctx->fs_fragmented),
15483 ctx->fs_fragmented), 14783 frag_percent / 10, frag_percent % 10);
15484 ctx->fs_fragmented, frag_percent / 10, frag_percent % 10);
15485 printf (_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"), 14784 printf (_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
15486 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count); 14785 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
15487 printf (P_("%8d block used (%d%%)\n", "%8d blocks used (%d%%)\n", 14786 printf ("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
15488 blocks_used), 14787 (int) ((long long) 100 * blocks_used / blocks));
15489 blocks_used, (int) ((long long) 100 * blocks_used / blocks)); 14788 printf ("%8d bad block%s\n", P_E2("", "s", ctx->fs_badblocks_count));
15490 printf (P_("%8d bad block\n", "%8d bad blocks\n", 14789 printf ("%8d large file%s\n", P_E2("", "s", ctx->large_files));
15491 ctx->fs_badblocks_count), ctx->fs_badblocks_count); 14790 printf ("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
15492 printf (P_("%8d large file\n", "%8d large files\n", 14791 printf ("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
15493 ctx->large_files), ctx->large_files); 14792 printf ("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
15494 printf (P_("\n%8d regular file\n", "\n%8d regular files\n", 14793 printf ("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
15495 ctx->fs_regular_count), ctx->fs_regular_count); 14794 printf ("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
15496 printf (P_("%8d directory\n", "%8d directories\n", 14795 printf ("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
15497 ctx->fs_directory_count), ctx->fs_directory_count); 14796 printf ("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
15498 printf (P_("%8d character device file\n", 14797 printf (" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
15499 "%8d character device files\n", ctx->fs_chardev_count), 14798 printf ("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
15500 ctx->fs_chardev_count); 14799 printf ("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
15501 printf (P_("%8d block device file\n", "%8d block device files\n",
15502 ctx->fs_blockdev_count), ctx->fs_blockdev_count);
15503 printf (P_("%8d fifo\n", "%8d fifos\n", ctx->fs_fifo_count),
15504 ctx->fs_fifo_count);
15505 printf (P_("%8d link\n", "%8d links\n",
15506 ctx->fs_links_count - dir_links),
15507 ctx->fs_links_count - dir_links);
15508 printf (P_("%8d symbolic link", "%8d symbolic links",
15509 ctx->fs_symlinks_count), ctx->fs_symlinks_count);
15510 printf (P_(" (%d fast symbolic link)\n", " (%d fast symbolic links)\n",
15511 ctx->fs_fast_symlinks_count), ctx->fs_fast_symlinks_count);
15512 printf (P_("%8d socket\n", "%8d sockets\n", ctx->fs_sockets_count),
15513 ctx->fs_sockets_count);
15514 printf ("--------\n");
15515 printf (P_("%8d file\n", "%8d files\n",
15516 ctx->fs_total_count - dir_links),
15517 ctx->fs_total_count - dir_links);
15518} 14800}
15519 14801
15520static void check_mount(e2fsck_t ctx) 14802static void check_mount(e2fsck_t ctx)
@@ -15677,12 +14959,13 @@ struct percent_tbl {
15677 int max_pass; 14959 int max_pass;
15678 int table[32]; 14960 int table[32];
15679}; 14961};
15680static struct percent_tbl e2fsck_tbl = { 14962static const struct percent_tbl e2fsck_tbl = {
15681 5, { 0, 70, 90, 92, 95, 100 } 14963 5, { 0, 70, 90, 92, 95, 100 }
15682}; 14964};
14965
15683static char bar[128], spaces[128]; 14966static char bar[128], spaces[128];
15684 14967
15685static float calc_percent(struct percent_tbl *tbl, int pass, int curr, 14968static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
15686 int max) 14969 int max)
15687{ 14970{
15688 float percent; 14971 float percent;
@@ -15854,7 +15137,7 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts)
15854 int ea_ver; 15137 int ea_ver;
15855 int extended_usage = 0; 15138 int extended_usage = 0;
15856 15139
15857 buf = string_copy(ctx, opts, 0); 15140 buf = string_copy(opts, 0);
15858 for (token = buf; token && *token; token = next) { 15141 for (token = buf; token && *token; token = next) {
15859 p = strchr(token, ','); 15142 p = strchr(token, ',');
15860 next = 0; 15143 next = 0;
@@ -15885,12 +15168,12 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts)
15885 extended_usage++; 15168 extended_usage++;
15886 } 15169 }
15887 if (extended_usage) { 15170 if (extended_usage) {
15888 fprintf(stderr, _("Extended options are separated by commas, " 15171 bb_error_msg_and_die(
15172 "Extended options are separated by commas, "
15889 "and may take an argument which\n" 15173 "and may take an argument which\n"
15890 "is set off by an equals ('=') sign. " 15174 "is set off by an equals ('=') sign. "
15891 "Valid raid options are:\n" 15175 "Valid raid options are:\n"
15892 "\tea_ver=<ea_version (1 or 2)\n\n")); 15176 "\tea_ver=<ea_version (1 or 2)\n\n");
15893 exit(1);
15894 } 15177 }
15895} 15178}
15896 15179
@@ -16003,7 +15286,7 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
16003 ctx->inode_buffer_blocks = atoi(optarg); 15286 ctx->inode_buffer_blocks = atoi(optarg);
16004 break; 15287 break;
16005 case 'j': 15288 case 'j':
16006 ctx->journal_name = string_copy(ctx, optarg, 0); 15289 ctx->journal_name = string_copy(optarg, 0);
16007 break; 15290 break;
16008 case 'P': 15291 case 'P':
16009 ctx->process_inode_size = atoi(optarg); 15292 ctx->process_inode_size = atoi(optarg);
@@ -16011,7 +15294,7 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
16011 case 'L': 15294 case 'L':
16012 replace_bad_blocks++; 15295 replace_bad_blocks++;
16013 case 'l': 15296 case 'l':
16014 bad_blocks_file = string_copy(ctx, optarg, 0); 15297 bad_blocks_file = string_copy(optarg, 0);
16015 break; 15298 break;
16016 case 'd': 15299 case 'd':
16017 ctx->options |= E2F_OPT_DEBUG; 15300 ctx->options |= E2F_OPT_DEBUG;
@@ -16145,12 +15428,12 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
16145 return 0; 15428 return 0;
16146} 15429}
16147 15430
16148static const char *my_ver_string = E2FSPROGS_VERSION; 15431static const char my_ver_string[] = E2FSPROGS_VERSION;
16149static const char *my_ver_date = E2FSPROGS_DATE; 15432static const char my_ver_date[] = E2FSPROGS_DATE;
16150 15433
16151int e2fsck_main (int argc, char *argv[]) 15434int e2fsck_main (int argc, char *argv[])
16152{ 15435{
16153 errcode_t retval = 0; 15436 errcode_t retval;
16154 int exit_value = FSCK_OK; 15437 int exit_value = FSCK_OK;
16155 ext2_filsys fs = 0; 15438 ext2_filsys fs = 0;
16156 io_manager io_ptr; 15439 io_manager io_ptr;
@@ -16302,7 +15585,7 @@ restart:
16302 */ 15585 */
16303 if (ctx->device_name == 0 && 15586 if (ctx->device_name == 0 &&
16304 (sb->s_volume_name[0] != 0)) { 15587 (sb->s_volume_name[0] != 0)) {
16305 ctx->device_name = string_copy(ctx, sb->s_volume_name, 15588 ctx->device_name = string_copy(sb->s_volume_name,
16306 sizeof(sb->s_volume_name)); 15589 sizeof(sb->s_volume_name));
16307 } 15590 }
16308 if (ctx->device_name == 0) 15591 if (ctx->device_name == 0)