mirror of https://github.com/vitalif/e2fsprogs
Change e2fsck to use a red/black tree in pass1b, to remove O(n**2)
algorithms. Makes e2fsck much, much faster in certain rare cases where the filesystem is severely corrupted.bitmap-optimize
parent
fe4dd429dc
commit
838e773e7a
|
@ -1,3 +1,13 @@
|
|||
2002-08-01 Theodore Ts'o <tytso@mit.edu>
|
||||
|
||||
* dict.c, dict.h: New file from kazlib 1.20 which implements a
|
||||
red-black tree
|
||||
|
||||
* pass1b.c: Massive changes to take advantage of dict.c. This
|
||||
removes several O(n**2) algorithms from the rare case
|
||||
where there are a large number of blocks claimed by
|
||||
multiple inodes.
|
||||
|
||||
2002-07-24 Theodore Ts'o <tytso@mit.edu>
|
||||
|
||||
* e2fsck.8.in, e2fsck.h, pass3.c (e2fsck_pass3), unix.c, rehash.c:
|
||||
|
|
|
@ -54,13 +54,13 @@ PROFILED_DEPLIBS= $(PROFILED_LIBEXT2FS) $(PROFILED_LIBCOM_ERR) \
|
|||
#
|
||||
#MCHECK= -DMCHECK
|
||||
|
||||
OBJS= unix.o e2fsck.o super.o pass1.o pass1b.o pass2.o pass3.o pass4.o \
|
||||
OBJS= dict.o unix.o e2fsck.o super.o pass1.o pass1b.o pass2.o pass3.o pass4.o \
|
||||
pass5.o journal.o swapfs.o badblocks.o util.o dirinfo.o dx_dirinfo.o \
|
||||
ehandler.o problem.o message.o recovery.o region.o revoke.o \
|
||||
ea_refcount.o rehash.o $(MTRACE_OBJ)
|
||||
|
||||
PROFILED_OBJS= profiled/unix.o profiled/e2fsck.o profiled/super.o \
|
||||
profiled/pass1.o profiled/pass1b.o \
|
||||
PROFILED_OBJS= profiled/dict.o profiled/unix.o profiled/e2fsck.o \
|
||||
profiled/super.o profiled/pass1.o profiled/pass1b.o \
|
||||
profiled/pass2.o profiled/pass3.o profiled/pass4.o profiled/pass5.o \
|
||||
profiled/journal.o profiled/badblocks.o profiled/util.o \
|
||||
profiled/dirinfo.o profiled/dx_dirinfo.o profiled/ehandler.o \
|
||||
|
@ -69,6 +69,7 @@ PROFILED_OBJS= profiled/unix.o profiled/e2fsck.o profiled/super.o \
|
|||
profiled/ea_refcount.o profiled/rehash.o
|
||||
|
||||
SRCS= $(srcdir)/e2fsck.c \
|
||||
$(srcdir)/dict.c \
|
||||
$(srcdir)/super.c \
|
||||
$(srcdir)/pass1.c \
|
||||
$(srcdir)/pass1b.c \
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Dictionary Abstract Data Type
|
||||
* Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
|
||||
*
|
||||
* Free Software License:
|
||||
*
|
||||
* All rights are reserved by the author, with the following exceptions:
|
||||
* Permission is granted to freely reproduce and distribute this software,
|
||||
* possibly in exchange for a fee, provided that this copyright notice appears
|
||||
* intact. Permission is also granted to adapt this software to produce
|
||||
* derivative works, as long as the modified versions carry this copyright
|
||||
* notice and additional notices stating that the work has been modified.
|
||||
* This source code may be translated into executable form and incorporated
|
||||
* into proprietary software; there is no requirement for such software to
|
||||
* contain a copyright notice related to this source.
|
||||
*
|
||||
* $Id: dict.h,v 1.22.2.6 2000/11/13 01:36:44 kaz Exp $
|
||||
* $Name: kazlib_1_20 $
|
||||
*/
|
||||
|
||||
#ifndef DICT_H
|
||||
#define DICT_H
|
||||
|
||||
#include <limits.h>
|
||||
#ifdef KAZLIB_SIDEEFFECT_DEBUG
|
||||
#include "sfx.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Blurb for inclusion into C++ translation units
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef unsigned long dictcount_t;
|
||||
#define DICTCOUNT_T_MAX ULONG_MAX
|
||||
|
||||
/*
|
||||
* The dictionary is implemented as a red-black tree
|
||||
*/
|
||||
|
||||
typedef enum { dnode_red, dnode_black } dnode_color_t;
|
||||
|
||||
typedef struct dnode_t {
|
||||
#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
|
||||
struct dnode_t *dict_left;
|
||||
struct dnode_t *dict_right;
|
||||
struct dnode_t *dict_parent;
|
||||
dnode_color_t dict_color;
|
||||
const void *dict_key;
|
||||
void *dict_data;
|
||||
#else
|
||||
int dict_dummy;
|
||||
#endif
|
||||
} dnode_t;
|
||||
|
||||
typedef int (*dict_comp_t)(const void *, const void *);
|
||||
typedef dnode_t *(*dnode_alloc_t)(void *);
|
||||
typedef void (*dnode_free_t)(dnode_t *, void *);
|
||||
|
||||
typedef struct dict_t {
|
||||
#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
|
||||
dnode_t dict_nilnode;
|
||||
dictcount_t dict_nodecount;
|
||||
dictcount_t dict_maxcount;
|
||||
dict_comp_t dict_compare;
|
||||
dnode_alloc_t dict_allocnode;
|
||||
dnode_free_t dict_freenode;
|
||||
void *dict_context;
|
||||
int dict_dupes;
|
||||
#else
|
||||
int dict_dummmy;
|
||||
#endif
|
||||
} dict_t;
|
||||
|
||||
typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
|
||||
|
||||
typedef struct dict_load_t {
|
||||
#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
|
||||
dict_t *dict_dictptr;
|
||||
dnode_t dict_nilnode;
|
||||
#else
|
||||
int dict_dummmy;
|
||||
#endif
|
||||
} dict_load_t;
|
||||
|
||||
extern dict_t *dict_create(dictcount_t, dict_comp_t);
|
||||
extern void dict_set_allocator(dict_t *, dnode_alloc_t, dnode_free_t, void *);
|
||||
extern void dict_destroy(dict_t *);
|
||||
extern void dict_free_nodes(dict_t *);
|
||||
extern void dict_free(dict_t *);
|
||||
extern dict_t *dict_init(dict_t *, dictcount_t, dict_comp_t);
|
||||
extern void dict_init_like(dict_t *, const dict_t *);
|
||||
extern int dict_verify(dict_t *);
|
||||
extern int dict_similar(const dict_t *, const dict_t *);
|
||||
extern dnode_t *dict_lookup(dict_t *, const void *);
|
||||
extern dnode_t *dict_lower_bound(dict_t *, const void *);
|
||||
extern dnode_t *dict_upper_bound(dict_t *, const void *);
|
||||
extern void dict_insert(dict_t *, dnode_t *, const void *);
|
||||
extern dnode_t *dict_delete(dict_t *, dnode_t *);
|
||||
extern int dict_alloc_insert(dict_t *, const void *, void *);
|
||||
extern void dict_delete_free(dict_t *, dnode_t *);
|
||||
extern dnode_t *dict_first(dict_t *);
|
||||
extern dnode_t *dict_last(dict_t *);
|
||||
extern dnode_t *dict_next(dict_t *, dnode_t *);
|
||||
extern dnode_t *dict_prev(dict_t *, dnode_t *);
|
||||
extern dictcount_t dict_count(dict_t *);
|
||||
extern int dict_isempty(dict_t *);
|
||||
extern int dict_isfull(dict_t *);
|
||||
extern int dict_contains(dict_t *, dnode_t *);
|
||||
extern void dict_allow_dupes(dict_t *);
|
||||
extern int dnode_is_in_a_dict(dnode_t *);
|
||||
extern dnode_t *dnode_create(void *);
|
||||
extern dnode_t *dnode_init(dnode_t *, void *);
|
||||
extern void dnode_destroy(dnode_t *);
|
||||
extern void *dnode_get(dnode_t *);
|
||||
extern const void *dnode_getkey(dnode_t *);
|
||||
extern void dnode_put(dnode_t *, void *);
|
||||
extern void dict_process(dict_t *, void *, dnode_process_t);
|
||||
extern void dict_load_begin(dict_load_t *, dict_t *);
|
||||
extern void dict_load_next(dict_load_t *, dnode_t *, const void *);
|
||||
extern void dict_load_end(dict_load_t *);
|
||||
extern void dict_merge(dict_t *, dict_t *);
|
||||
|
||||
#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
|
||||
#ifdef KAZLIB_SIDEEFFECT_DEBUG
|
||||
#define dict_isfull(D) (SFX_CHECK(D)->dict_nodecount == (D)->dict_maxcount)
|
||||
#else
|
||||
#define dict_isfull(D) ((D)->dict_nodecount == (D)->dict_maxcount)
|
||||
#endif
|
||||
#define dict_count(D) ((D)->dict_nodecount)
|
||||
#define dict_isempty(D) ((D)->dict_nodecount == 0)
|
||||
#define dnode_get(N) ((N)->dict_data)
|
||||
#define dnode_getkey(N) ((N)->dict_key)
|
||||
#define dnode_put(N, X) ((N)->dict_data = (X))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
447
e2fsck/pass1b.c
447
e2fsck/pass1b.c
|
@ -36,48 +36,25 @@
|
|||
#include "e2fsck.h"
|
||||
|
||||
#include "problem.h"
|
||||
#include "dict.h"
|
||||
|
||||
/* Define an extension to the ext2 library's block count information */
|
||||
#define BLOCK_COUNT_EXTATTR (-5)
|
||||
|
||||
/*
|
||||
* This is structure is allocated for each time that a block is
|
||||
* claimed by more than one file. So if a particular block is claimed
|
||||
* by 3 files, then three copies of this structure will be allocated,
|
||||
* one for each conflict.
|
||||
*
|
||||
* The linked list structure is as follows:
|
||||
*
|
||||
* dup_blk --> block #34 --> block #35 --> block #47
|
||||
* inode #12 inode #14 inode #17
|
||||
* num_bad = 3 num_bad = 2 num_bad = 2
|
||||
* | | |
|
||||
* V V V
|
||||
* block #34 block #35 block #47
|
||||
* inode #14 inode #15 inode #23
|
||||
* |
|
||||
* V
|
||||
* block #34
|
||||
* inode #15
|
||||
*
|
||||
* The num_bad field indicates how many inodes are sharing a
|
||||
* particular block, and is only stored in the first element of the
|
||||
* linked list for a particular block. As the block conflicts are
|
||||
* resolved, num_bad is decremented; when it reaches 1, then we no
|
||||
* longer need to worry about that block.
|
||||
*/
|
||||
struct dup_block {
|
||||
blk_t block; /* Block number */
|
||||
ext2_ino_t ino; /* Inode number */
|
||||
int num_bad;
|
||||
int flags;
|
||||
/* Pointer to next dup record with different block */
|
||||
struct dup_block *next_block;
|
||||
/* Pointer to next dup record with different inode */
|
||||
struct dup_block *next_inode;
|
||||
struct block_el {
|
||||
blk_t block;
|
||||
struct block_el *next;
|
||||
};
|
||||
|
||||
#define FLAG_EXTATTR (1)
|
||||
struct inode_el {
|
||||
ext2_ino_t inode;
|
||||
struct inode_el *next;
|
||||
};
|
||||
|
||||
struct dup_block {
|
||||
int num_bad;
|
||||
struct inode_el *inode_list;
|
||||
};
|
||||
|
||||
/*
|
||||
* This structure stores information about a particular inode which
|
||||
|
@ -87,38 +64,129 @@ struct dup_block {
|
|||
* of multiply-claimed blocks.
|
||||
*/
|
||||
struct dup_inode {
|
||||
ext2_ino_t ino, dir;
|
||||
ext2_ino_t dir;
|
||||
int num_dupblocks;
|
||||
struct ext2_inode inode;
|
||||
struct dup_inode *next;
|
||||
struct block_el *block_list;
|
||||
};
|
||||
|
||||
static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
|
||||
e2_blkcnt_t blockcnt, blk_t ref_blk,
|
||||
int ref_offset, void *priv_data);
|
||||
static void delete_file(e2fsck_t ctx, struct dup_inode *dp,
|
||||
char *block_buf);
|
||||
static int clone_file(e2fsck_t ctx, struct dup_inode *dp, char* block_buf);
|
||||
static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
|
||||
struct dup_inode *dp, char *block_buf);
|
||||
static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
|
||||
struct dup_inode *dp, char* block_buf);
|
||||
static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
|
||||
|
||||
static void pass1b(e2fsck_t ctx, char *block_buf);
|
||||
static void pass1c(e2fsck_t ctx, char *block_buf);
|
||||
static void pass1d(e2fsck_t ctx, char *block_buf);
|
||||
|
||||
static struct dup_block *dup_blk = 0;
|
||||
static struct dup_inode *dup_ino = 0;
|
||||
static int dup_inode_count = 0;
|
||||
|
||||
static dict_t blk_dict, ino_dict;
|
||||
|
||||
static ext2fs_inode_bitmap inode_dup_map;
|
||||
|
||||
static int dict_int_cmp(const void *a, const void *b)
|
||||
{
|
||||
int ia, ib;
|
||||
|
||||
ia = (int) a;
|
||||
ib = (int) b;
|
||||
|
||||
return (ia-ib);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a duplicate block record
|
||||
*/
|
||||
static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
|
||||
struct ext2_inode *inode)
|
||||
{
|
||||
dnode_t *n;
|
||||
struct dup_block *db;
|
||||
struct dup_inode *di;
|
||||
struct block_el *blk_el;
|
||||
struct inode_el *ino_el;
|
||||
|
||||
n = dict_lookup(&blk_dict, (void *) blk);
|
||||
if (n)
|
||||
db = (struct dup_block *) dnode_get(n);
|
||||
else {
|
||||
db = (struct dup_block *) e2fsck_allocate_memory(ctx,
|
||||
sizeof(struct dup_block), "duplicate block header");
|
||||
db->num_bad = 0;
|
||||
db->inode_list = 0;
|
||||
dict_alloc_insert(&blk_dict, (void *) blk, db);
|
||||
}
|
||||
ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
|
||||
sizeof(struct inode_el), "inode element");
|
||||
ino_el->inode = ino;
|
||||
ino_el->next = db->inode_list;
|
||||
db->inode_list = ino_el;
|
||||
db->num_bad++;
|
||||
|
||||
n = dict_lookup(&ino_dict, (void *) ino);
|
||||
if (n)
|
||||
di = (struct dup_inode *) dnode_get(n);
|
||||
else {
|
||||
di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
|
||||
sizeof(struct dup_inode), "duplicate inode header");
|
||||
di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0 ;
|
||||
di->num_dupblocks = 0;
|
||||
di->block_list = 0;
|
||||
di->inode = *inode;
|
||||
dict_alloc_insert(&ino_dict, (void *) ino, di);
|
||||
}
|
||||
blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
|
||||
sizeof(struct block_el), "block element");
|
||||
blk_el->block = blk;
|
||||
blk_el->next = di->block_list;
|
||||
di->block_list = blk_el;
|
||||
di->num_dupblocks++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a duplicate inode record
|
||||
*/
|
||||
static void inode_dnode_free(dnode_t *node, void *context)
|
||||
{
|
||||
struct dup_inode *di;
|
||||
struct block_el *p, *next;
|
||||
|
||||
di = (struct dup_inode *) dnode_get(node);
|
||||
for (p = di->block_list; p; p = next) {
|
||||
next = p->next;
|
||||
free(p);
|
||||
}
|
||||
free(node);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a duplicate block record
|
||||
*/
|
||||
static void block_dnode_free(dnode_t *node, void *context)
|
||||
{
|
||||
struct dup_block *db;
|
||||
struct inode_el *p, *next;
|
||||
|
||||
db = (struct dup_block *) dnode_get(node);
|
||||
for (p = db->inode_list; p; p = next) {
|
||||
next = p->next;
|
||||
free(p);
|
||||
}
|
||||
free(node);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Main procedure for handling duplicate blocks
|
||||
*/
|
||||
void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
|
||||
{
|
||||
ext2_filsys fs = ctx->fs;
|
||||
struct dup_block *p, *q, *next_p, *next_q;
|
||||
struct dup_inode *r, *next_r;
|
||||
struct problem_context pctx;
|
||||
|
||||
clear_problem_context(&pctx);
|
||||
|
@ -130,6 +198,11 @@ void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
|
|||
ctx->flags |= E2F_FLAG_ABORT;
|
||||
return;
|
||||
}
|
||||
|
||||
dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
|
||||
dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
|
||||
dict_set_allocator(&ino_dict, NULL, inode_dnode_free, NULL);
|
||||
dict_set_allocator(&blk_dict, NULL, block_dnode_free, NULL);
|
||||
|
||||
pass1b(ctx, block_buf);
|
||||
pass1c(ctx, block_buf);
|
||||
|
@ -139,28 +212,18 @@ void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
|
|||
* Time to free all of the accumulated data structures that we
|
||||
* don't need anymore.
|
||||
*/
|
||||
ext2fs_free_inode_bitmap(inode_dup_map); inode_dup_map = 0;
|
||||
ext2fs_free_block_bitmap(ctx->block_dup_map); ctx->block_dup_map = 0;
|
||||
for (p = dup_blk; p; p = next_p) {
|
||||
next_p = p->next_block;
|
||||
for (q = p; q; q = next_q) {
|
||||
next_q = q->next_inode;
|
||||
ext2fs_free_mem((void **) &q);
|
||||
}
|
||||
}
|
||||
for (r = dup_ino; r; r = next_r) {
|
||||
next_r = r->next;
|
||||
ext2fs_free_mem((void **) &r);
|
||||
}
|
||||
dict_free_nodes(&ino_dict);
|
||||
dict_free_nodes(&blk_dict);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan the inodes looking for inodes that contain duplicate blocks.
|
||||
*/
|
||||
struct process_block_struct {
|
||||
e2fsck_t ctx;
|
||||
ext2_ino_t ino;
|
||||
int dup_blocks;
|
||||
e2fsck_t ctx;
|
||||
struct ext2_inode *inode;
|
||||
struct problem_context *pctx;
|
||||
};
|
||||
|
||||
|
@ -171,10 +234,7 @@ static void pass1b(e2fsck_t ctx, char *block_buf)
|
|||
struct ext2_inode inode;
|
||||
ext2_inode_scan scan;
|
||||
struct process_block_struct pb;
|
||||
struct dup_inode *dp;
|
||||
struct dup_block *q, *r;
|
||||
struct problem_context pctx;
|
||||
int i, ea_flag;
|
||||
|
||||
clear_problem_context(&pctx);
|
||||
|
||||
|
@ -205,6 +265,7 @@ static void pass1b(e2fsck_t ctx, char *block_buf)
|
|||
|
||||
pb.ino = ino;
|
||||
pb.dup_blocks = 0;
|
||||
pb.inode = &inode;
|
||||
pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
|
||||
process_pass1b_block, &pb);
|
||||
if (inode.i_file_acl)
|
||||
|
@ -212,16 +273,8 @@ static void pass1b(e2fsck_t ctx, char *block_buf)
|
|||
BLOCK_COUNT_EXTATTR, 0, 0, &pb);
|
||||
if (pb.dup_blocks) {
|
||||
end_problem_latch(ctx, PR_LATCH_DBLOCK);
|
||||
dp = (struct dup_inode *) e2fsck_allocate_memory(ctx,
|
||||
sizeof(struct dup_inode),
|
||||
"duplicate inode record");
|
||||
dp->ino = ino;
|
||||
dp->dir = 0;
|
||||
dp->inode = inode;
|
||||
dp->num_dupblocks = pb.dup_blocks;
|
||||
dp->next = dup_ino;
|
||||
dup_ino = dp;
|
||||
if (ino != EXT2_BAD_INO)
|
||||
if (ino >= EXT2_FIRST_INODE(fs->super) ||
|
||||
ino == EXT2_ROOT_INO)
|
||||
dup_inode_count++;
|
||||
}
|
||||
if (pctx.errcode)
|
||||
|
@ -238,21 +291,6 @@ static void pass1b(e2fsck_t ctx, char *block_buf)
|
|||
}
|
||||
ext2fs_close_inode_scan(scan);
|
||||
e2fsck_use_inode_shortcuts(ctx, 0);
|
||||
/*
|
||||
* Set the num_bad field
|
||||
*/
|
||||
for (q = dup_blk; q; q = q->next_block) {
|
||||
i = 0;
|
||||
ea_flag = 0;
|
||||
for (r = q; r; r = r->next_inode) {
|
||||
if (r->flags & FLAG_EXTATTR) {
|
||||
if (ea_flag++)
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
q->num_bad = i;
|
||||
}
|
||||
}
|
||||
|
||||
static int process_pass1b_block(ext2_filsys fs,
|
||||
|
@ -263,7 +301,6 @@ static int process_pass1b_block(ext2_filsys fs,
|
|||
void *priv_data)
|
||||
{
|
||||
struct process_block_struct *p;
|
||||
struct dup_block *dp, *q;
|
||||
e2fsck_t ctx;
|
||||
|
||||
if (HOLE_BLKADDR(*block_nr))
|
||||
|
@ -271,37 +308,19 @@ static int process_pass1b_block(ext2_filsys fs,
|
|||
p = (struct process_block_struct *) priv_data;
|
||||
ctx = p->ctx;
|
||||
|
||||
if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
|
||||
/* OK, this is a duplicate block */
|
||||
if (p->ino != EXT2_BAD_INO) {
|
||||
p->pctx->blk = *block_nr;
|
||||
fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
|
||||
}
|
||||
p->dup_blocks++;
|
||||
ext2fs_mark_block_bitmap(ctx->block_dup_map, *block_nr);
|
||||
ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
|
||||
dp = (struct dup_block *) e2fsck_allocate_memory(ctx,
|
||||
sizeof(struct dup_block),
|
||||
"duplicate block record");
|
||||
dp->block = *block_nr;
|
||||
dp->ino = p->ino;
|
||||
dp->num_bad = 0;
|
||||
dp->flags = (blockcnt == BLOCK_COUNT_EXTATTR) ?
|
||||
FLAG_EXTATTR : 0;
|
||||
q = dup_blk;
|
||||
while (q) {
|
||||
if (q->block == *block_nr)
|
||||
break;
|
||||
q = q->next_block;
|
||||
}
|
||||
if (q) {
|
||||
dp->next_inode = q->next_inode;
|
||||
q->next_inode = dp;
|
||||
} else {
|
||||
dp->next_block = dup_blk;
|
||||
dup_blk = dp;
|
||||
}
|
||||
if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
|
||||
return 0;
|
||||
|
||||
/* OK, this is a duplicate block */
|
||||
if (p->ino != EXT2_BAD_INO) {
|
||||
p->pctx->blk = *block_nr;
|
||||
fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
|
||||
}
|
||||
p->dup_blocks++;
|
||||
ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
|
||||
|
||||
add_dupe(ctx, p->ino, *block_nr, p->inode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -323,6 +342,7 @@ static int search_dirent_proc(ext2_ino_t dir, int entry,
|
|||
{
|
||||
struct search_dir_struct *sd;
|
||||
struct dup_inode *p;
|
||||
dnode_t *n;
|
||||
|
||||
sd = (struct search_dir_struct *) priv_data;
|
||||
|
||||
|
@ -330,19 +350,14 @@ static int search_dirent_proc(ext2_ino_t dir, int entry,
|
|||
/* Should abort this inode, but not everything */
|
||||
return 0;
|
||||
|
||||
if (!dirent->inode || (entry < DIRENT_OTHER_FILE) ||
|
||||
if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
|
||||
!ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
|
||||
return 0;
|
||||
|
||||
for (p = dup_ino; p; p = p->next) {
|
||||
if ((p->ino >= sd->first_inode) &&
|
||||
(p->ino == dirent->inode))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!p || p->dir)
|
||||
n = dict_lookup(&ino_dict, (void *) dirent->inode);
|
||||
if (!n)
|
||||
return 0;
|
||||
|
||||
p = (struct dup_inode *) dnode_get(n);
|
||||
p->dir = dir;
|
||||
sd->count--;
|
||||
|
||||
|
@ -353,8 +368,6 @@ static int search_dirent_proc(ext2_ino_t dir, int entry,
|
|||
static void pass1c(e2fsck_t ctx, char *block_buf)
|
||||
{
|
||||
ext2_filsys fs = ctx->fs;
|
||||
struct dup_inode *p;
|
||||
int inodes_left = dup_inode_count;
|
||||
struct search_dir_struct sd;
|
||||
struct problem_context pctx;
|
||||
|
||||
|
@ -362,22 +375,11 @@ static void pass1c(e2fsck_t ctx, char *block_buf)
|
|||
|
||||
fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
|
||||
|
||||
/*
|
||||
* First check to see if any of the inodes with dup blocks is
|
||||
* a special inode. (Note that the bad block inode isn't
|
||||
* counted.)
|
||||
*/
|
||||
for (p = dup_ino; p; p = p->next) {
|
||||
if ((p->ino < EXT2_FIRST_INODE(fs->super)) &&
|
||||
(p->ino != EXT2_BAD_INO))
|
||||
inodes_left--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search through all directories to translate inodes to names
|
||||
* (by searching for the containing directory for that inode.)
|
||||
*/
|
||||
sd.count = inodes_left;
|
||||
sd.count = dup_inode_count;
|
||||
sd.first_inode = EXT2_FIRST_INODE(fs->super);
|
||||
sd.max_inode = fs->super->s_inodes_count;
|
||||
ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
|
||||
|
@ -387,48 +389,50 @@ static void pass1c(e2fsck_t ctx, char *block_buf)
|
|||
static void pass1d(e2fsck_t ctx, char *block_buf)
|
||||
{
|
||||
ext2_filsys fs = ctx->fs;
|
||||
struct dup_inode *p, *s;
|
||||
struct dup_block *q, *r;
|
||||
ext2_ino_t *shared;
|
||||
struct dup_inode *p, *t;
|
||||
struct dup_block *q;
|
||||
ext2_ino_t *shared, ino;
|
||||
int shared_len;
|
||||
int i;
|
||||
int file_ok;
|
||||
int meta_data = 0;
|
||||
struct problem_context pctx;
|
||||
|
||||
dnode_t *n, *m;
|
||||
struct block_el *s;
|
||||
struct inode_el *r;
|
||||
|
||||
clear_problem_context(&pctx);
|
||||
|
||||
fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
|
||||
e2fsck_read_bitmaps(ctx);
|
||||
|
||||
pctx.num = dup_inode_count;
|
||||
pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
|
||||
fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
|
||||
shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
|
||||
sizeof(ext2_ino_t) * dup_inode_count,
|
||||
sizeof(ext2_ino_t) * dict_count(&ino_dict),
|
||||
"Shared inode list");
|
||||
for (p = dup_ino; p; p = p->next) {
|
||||
for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
|
||||
p = (struct dup_inode *) dnode_get(n);
|
||||
shared_len = 0;
|
||||
file_ok = 1;
|
||||
if (p->ino == EXT2_BAD_INO)
|
||||
ino = (ext2_ino_t) dnode_getkey(n);
|
||||
if (ino == EXT2_BAD_INO)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Search through the duplicate records to see which
|
||||
* inodes share blocks with this one
|
||||
* Find all of the inodes which share blocks with this
|
||||
* one. First we find all of the duplicate blocks
|
||||
* belonging to this inode, and then search each block
|
||||
* get the list of inodes, and merge them together.
|
||||
*/
|
||||
for (q = dup_blk; q; q = q->next_block) {
|
||||
/*
|
||||
* See if this block is used by this inode.
|
||||
* If it isn't, continue.
|
||||
*/
|
||||
for (r = q; r; r = r->next_inode)
|
||||
if (r->ino == p->ino)
|
||||
break;
|
||||
if (!r)
|
||||
continue;
|
||||
for (s = p->block_list; s; s = s->next) {
|
||||
m = dict_lookup(&blk_dict, (void *) s->block);
|
||||
if (!m)
|
||||
continue; /* Should never happen... */
|
||||
q = (struct dup_block *) dnode_get(m);
|
||||
if (q->num_bad > 1)
|
||||
file_ok = 0;
|
||||
if (check_if_fs_block(ctx, q->block)) {
|
||||
if (check_if_fs_block(ctx, s->block)) {
|
||||
file_ok = 0;
|
||||
meta_data = 1;
|
||||
}
|
||||
|
@ -439,14 +443,14 @@ static void pass1d(e2fsck_t ctx, char *block_buf)
|
|||
* if an inode is already in shared[], don't
|
||||
* add it again.
|
||||
*/
|
||||
for (r = q; r; r = r->next_inode) {
|
||||
if (r->ino == p->ino)
|
||||
for (r = q->inode_list; r; r = r->next) {
|
||||
if (r->inode == ino)
|
||||
continue;
|
||||
for (i = 0; i < shared_len; i++)
|
||||
if (shared[i] == r->ino)
|
||||
if (shared[i] == r->inode)
|
||||
break;
|
||||
if (i == shared_len) {
|
||||
shared[shared_len++] = r->ino;
|
||||
shared[shared_len++] = r->inode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -455,7 +459,7 @@ static void pass1d(e2fsck_t ctx, char *block_buf)
|
|||
* Report the inode that we are working on
|
||||
*/
|
||||
pctx.inode = &p->inode;
|
||||
pctx.ino = p->ino;
|
||||
pctx.ino = ino;
|
||||
pctx.dir = p->dir;
|
||||
pctx.blkcount = p->num_dupblocks;
|
||||
pctx.num = meta_data ? shared_len+1 : shared_len;
|
||||
|
@ -467,17 +471,16 @@ static void pass1d(e2fsck_t ctx, char *block_buf)
|
|||
fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
|
||||
|
||||
for (i = 0; i < shared_len; i++) {
|
||||
for (s = dup_ino; s; s = s->next)
|
||||
if (s->ino == shared[i])
|
||||
break;
|
||||
if (!s)
|
||||
continue;
|
||||
m = dict_lookup(&ino_dict, (void *) shared[i]);
|
||||
if (!m)
|
||||
continue; /* should never happen */
|
||||
t = (struct dup_inode *) dnode_get(m);
|
||||
/*
|
||||
* Report the inode that we are sharing with
|
||||
*/
|
||||
pctx.inode = &s->inode;
|
||||
pctx.ino = s->ino;
|
||||
pctx.dir = s->dir;
|
||||
pctx.inode = &t->inode;
|
||||
pctx.ino = shared[i];
|
||||
pctx.dir = t->dir;
|
||||
fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
|
||||
}
|
||||
if (file_ok) {
|
||||
|
@ -485,14 +488,14 @@ static void pass1d(e2fsck_t ctx, char *block_buf)
|
|||
continue;
|
||||
}
|
||||
if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
|
||||
pctx.errcode = clone_file(ctx, p, block_buf);
|
||||
pctx.errcode = clone_file(ctx, ino, p, block_buf);
|
||||
if (pctx.errcode)
|
||||
fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
|
||||
else
|
||||
continue;
|
||||
}
|
||||
if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
|
||||
delete_file(ctx, p, block_buf);
|
||||
delete_file(ctx, ino, p, block_buf);
|
||||
else
|
||||
ext2fs_unmark_valid(fs);
|
||||
}
|
||||
|
@ -503,12 +506,12 @@ static void pass1d(e2fsck_t ctx, char *block_buf)
|
|||
* Drop the refcount on the dup_block structure, and clear the entry
|
||||
* in the block_dup_map if appropriate.
|
||||
*/
|
||||
static void decrement_badcount(e2fsck_t ctx, struct dup_block *p)
|
||||
static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
|
||||
{
|
||||
p->num_bad--;
|
||||
if (p->num_bad <= 0 ||
|
||||
(p->num_bad == 1 && !check_if_fs_block(ctx, p->block)))
|
||||
ext2fs_unmark_block_bitmap(ctx->block_dup_map, p->block);
|
||||
(p->num_bad == 1 && !check_if_fs_block(ctx, block)))
|
||||
ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
|
||||
}
|
||||
|
||||
static int delete_file_block(ext2_filsys fs,
|
||||
|
@ -520,6 +523,7 @@ static int delete_file_block(ext2_filsys fs,
|
|||
{
|
||||
struct process_block_struct *pb;
|
||||
struct dup_block *p;
|
||||
dnode_t *n;
|
||||
e2fsck_t ctx;
|
||||
|
||||
pb = (struct process_block_struct *) priv_data;
|
||||
|
@ -529,11 +533,10 @@ static int delete_file_block(ext2_filsys fs,
|
|||
return 0;
|
||||
|
||||
if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
|
||||
for (p = dup_blk; p; p = p->next_block)
|
||||
if (p->block == *block_nr)
|
||||
break;
|
||||
if (p) {
|
||||
decrement_badcount(ctx, p);
|
||||
n = dict_lookup(&blk_dict, (void *) *block_nr);
|
||||
if (n) {
|
||||
p = (struct dup_block *) dnode_get(n);
|
||||
decrement_badcount(ctx, *block_nr, p);
|
||||
} else
|
||||
com_err("delete_file_block", 0,
|
||||
_("internal error; can't find dup_blk for %d\n"),
|
||||
|
@ -546,7 +549,8 @@ static int delete_file_block(ext2_filsys fs,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void delete_file(e2fsck_t ctx, struct dup_inode *dp, char* block_buf)
|
||||
static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
|
||||
struct dup_inode *dp, char* block_buf)
|
||||
{
|
||||
ext2_filsys fs = ctx->fs;
|
||||
struct process_block_struct pb;
|
||||
|
@ -554,29 +558,29 @@ static void delete_file(e2fsck_t ctx, struct dup_inode *dp, char* block_buf)
|
|||
struct problem_context pctx;
|
||||
|
||||
clear_problem_context(&pctx);
|
||||
pctx.ino = pb.ino = dp->ino;
|
||||
pctx.ino = pb.ino = ino;
|
||||
pb.dup_blocks = dp->num_dupblocks;
|
||||
pb.ctx = ctx;
|
||||
pctx.str = "delete_file";
|
||||
|
||||
pctx.errcode = ext2fs_block_iterate2(fs, dp->ino, 0, block_buf,
|
||||
pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
|
||||
delete_file_block, &pb);
|
||||
if (pctx.errcode)
|
||||
fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
|
||||
ext2fs_unmark_inode_bitmap(ctx->inode_used_map, dp->ino);
|
||||
ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, dp->ino);
|
||||
ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
|
||||
ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
|
||||
if (ctx->inode_bad_map)
|
||||
ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, dp->ino);
|
||||
ext2fs_unmark_inode_bitmap(fs->inode_map, dp->ino);
|
||||
ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
|
||||
ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
|
||||
ext2fs_mark_ib_dirty(fs);
|
||||
ext2fs_mark_bb_dirty(fs);
|
||||
e2fsck_read_inode(ctx, dp->ino, &inode, "delete_file");
|
||||
e2fsck_read_inode(ctx, ino, &inode, "delete_file");
|
||||
inode.i_links_count = 0;
|
||||
inode.i_dtime = time(0);
|
||||
if (inode.i_file_acl)
|
||||
delete_file_block(fs, &inode.i_file_acl,
|
||||
BLOCK_COUNT_EXTATTR, 0, 0, &pb);
|
||||
e2fsck_write_inode(ctx, dp->ino, &inode, "delete_file");
|
||||
e2fsck_write_inode(ctx, ino, &inode, "delete_file");
|
||||
}
|
||||
|
||||
struct clone_struct {
|
||||
|
@ -597,6 +601,7 @@ static int clone_file_block(ext2_filsys fs,
|
|||
blk_t new_block;
|
||||
errcode_t retval;
|
||||
struct clone_struct *cs = (struct clone_struct *) priv_data;
|
||||
dnode_t *n;
|
||||
e2fsck_t ctx;
|
||||
|
||||
ctx = cs->ctx;
|
||||
|
@ -605,10 +610,9 @@ static int clone_file_block(ext2_filsys fs,
|
|||
return 0;
|
||||
|
||||
if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
|
||||
for (p = dup_blk; p; p = p->next_block)
|
||||
if (p->block == *block_nr)
|
||||
break;
|
||||
if (p) {
|
||||
n = dict_lookup(&blk_dict, (void *) *block_nr);
|
||||
if (n) {
|
||||
p = (struct dup_block *) dnode_get(n);
|
||||
retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
|
||||
&new_block);
|
||||
if (retval) {
|
||||
|
@ -639,7 +643,7 @@ static int clone_file_block(ext2_filsys fs,
|
|||
cs->errcode = retval;
|
||||
return BLOCK_ABORT;
|
||||
}
|
||||
decrement_badcount(ctx, p);
|
||||
decrement_badcount(ctx, *block_nr, p);
|
||||
*block_nr = new_block;
|
||||
ext2fs_mark_block_bitmap(ctx->block_found_map,
|
||||
new_block);
|
||||
|
@ -653,13 +657,18 @@ static int clone_file_block(ext2_filsys fs,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int clone_file(e2fsck_t ctx, struct dup_inode *dp, char* block_buf)
|
||||
static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
|
||||
struct dup_inode *dp, char* block_buf)
|
||||
{
|
||||
ext2_filsys fs = ctx->fs;
|
||||
errcode_t retval;
|
||||
struct clone_struct cs;
|
||||
struct problem_context pctx;
|
||||
blk_t blk;
|
||||
dnode_t *n;
|
||||
struct inode_el *ino_el;
|
||||
struct dup_block *db;
|
||||
struct dup_inode *di;
|
||||
|
||||
clear_problem_context(&pctx);
|
||||
cs.errcode = 0;
|
||||
|
@ -669,12 +678,12 @@ static int clone_file(e2fsck_t ctx, struct dup_inode *dp, char* block_buf)
|
|||
if (retval)
|
||||
return retval;
|
||||
|
||||
if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dp->ino))
|
||||
cs.dir = dp->ino;
|
||||
if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
|
||||
cs.dir = ino;
|
||||
|
||||
pctx.ino = dp->ino;
|
||||
pctx.ino = ino;
|
||||
pctx.str = "clone_file";
|
||||
pctx.errcode = ext2fs_block_iterate2(fs, dp->ino, 0, block_buf,
|
||||
pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
|
||||
clone_file_block, &cs);
|
||||
ext2fs_mark_bb_dirty(fs);
|
||||
if (pctx.errcode) {
|
||||
|
@ -692,31 +701,25 @@ static int clone_file(e2fsck_t ctx, struct dup_inode *dp, char* block_buf)
|
|||
if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
|
||||
BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
|
||||
BLOCK_CHANGED)) {
|
||||
struct dup_block *p, *q;
|
||||
struct dup_inode *r;
|
||||
|
||||
e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
|
||||
/*
|
||||
* If we cloned the EA block, find all other inodes
|
||||
* which refered to that EA block, and modify
|
||||
* them to point to the new EA block.
|
||||
*/
|
||||
for (p = dup_blk; p; p = p->next_block) {
|
||||
if (p->block == blk)
|
||||
break;
|
||||
}
|
||||
for (q = p; q ; q = q->next_inode) {
|
||||
if (!(q->flags & FLAG_EXTATTR))
|
||||
n = dict_lookup(&blk_dict, (void *) blk);
|
||||
db = (struct dup_block *) dnode_get(n);
|
||||
for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
|
||||
if (ino_el->inode == ino)
|
||||
continue;
|
||||
for (r = dup_ino; r; r = r->next)
|
||||
if (r->ino == q->ino)
|
||||
break;
|
||||
if (r) {
|
||||
r->inode.i_file_acl = dp->inode.i_file_acl;
|
||||
e2fsck_write_inode(ctx, q->ino, &r->inode,
|
||||
"clone file EA");
|
||||
n = dict_lookup(&ino_dict, (void *) ino_el->inode);
|
||||
di = (struct dup_inode *) dnode_get(n);
|
||||
if (di->inode.i_file_acl == blk) {
|
||||
di->inode.i_file_acl = dp->inode.i_file_acl;
|
||||
e2fsck_write_inode(ctx, ino_el->inode,
|
||||
&dp->inode, "clone file EA");
|
||||
decrement_badcount(ctx, blk, db);
|
||||
}
|
||||
q->ino = 0; /* Should free the structure... */
|
||||
decrement_badcount(ctx, p);
|
||||
}
|
||||
}
|
||||
retval = 0;
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2002-08-01 Theodore Ts'o <tytso@mit.edu>
|
||||
|
||||
* f_dup, f_dup2, f_dup3, f_bbfile, f_dupfsblks: Update expect
|
||||
scripts to deal with ordering changes caused by use of a
|
||||
red-block tree in pass1b.
|
||||
|
||||
2002-07-19 Theodore Ts'o <tytso@mit.edu>
|
||||
|
||||
* f_expand, f_h_badnode, f_h_badroot: Modify the expect scripts to
|
||||
|
|
|
@ -13,8 +13,8 @@ Pass 1C: Scan directories for inodes with dup blocks.
|
|||
Pass 1D: Reconciling duplicate blocks
|
||||
(There are 3 inodes containing duplicate/bad blocks.)
|
||||
|
||||
File /termcap (inode #12, mod time Sun Jan 2 08:29:13 1994)
|
||||
has 2 duplicate block(s), shared with 1 file(s):
|
||||
File / (inode #2, mod time Sun Jan 2 08:29:13 1994)
|
||||
has 1 duplicate block(s), shared with 1 file(s):
|
||||
<The bad blocks inode> (inode #1, mod time Sun Jul 17 00:47:58 1994)
|
||||
Clone duplicate/bad blocks? yes
|
||||
|
||||
|
@ -23,8 +23,8 @@ File /lost+found (inode #11, mod time Sun Jan 2 08:28:40 1994)
|
|||
<The bad blocks inode> (inode #1, mod time Sun Jul 17 00:47:58 1994)
|
||||
Clone duplicate/bad blocks? yes
|
||||
|
||||
File / (inode #2, mod time Sun Jan 2 08:29:13 1994)
|
||||
has 1 duplicate block(s), shared with 1 file(s):
|
||||
File /termcap (inode #12, mod time Sun Jan 2 08:29:13 1994)
|
||||
has 2 duplicate block(s), shared with 1 file(s):
|
||||
<The bad blocks inode> (inode #1, mod time Sun Jul 17 00:47:58 1994)
|
||||
Clone duplicate/bad blocks? yes
|
||||
|
||||
|
|
|
@ -9,14 +9,14 @@ Pass 1C: Scan directories for inodes with dup blocks.
|
|||
Pass 1D: Reconciling duplicate blocks
|
||||
(There are 2 inodes containing duplicate/bad blocks.)
|
||||
|
||||
File /motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
|
||||
has 2 duplicate block(s), shared with 1 file(s):
|
||||
/termcap (inode #12, mod time Tue Sep 21 03:19:14 1993)
|
||||
Clone duplicate/bad blocks? yes
|
||||
|
||||
File /termcap (inode #12, mod time Tue Sep 21 03:19:14 1993)
|
||||
has 2 duplicate block(s), shared with 1 file(s):
|
||||
/motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
|
||||
Clone duplicate/bad blocks? yes
|
||||
|
||||
File /motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
|
||||
has 2 duplicate block(s), shared with 1 file(s):
|
||||
/termcap (inode #12, mod time Tue Sep 21 03:19:14 1993)
|
||||
Duplicated blocks already reassigned or cloned.
|
||||
|
||||
Pass 2: Checking directory structure
|
||||
|
|
|
@ -3,5 +3,5 @@ Pass 2: Checking directory structure
|
|||
Pass 3: Checking directory connectivity
|
||||
Pass 4: Checking reference counts
|
||||
Pass 5: Checking group summary information
|
||||
test_filesys: 13/16 files (7.7% non-contiguous), 40/100 blocks
|
||||
test_filesys: 13/16 files (15.4% non-contiguous), 40/100 blocks
|
||||
Exit status is 0
|
||||
|
|
|
@ -10,7 +10,7 @@ Pass 1C: Scan directories for inodes with dup blocks.
|
|||
Pass 1D: Reconciling duplicate blocks
|
||||
(There are 3 inodes containing duplicate/bad blocks.)
|
||||
|
||||
File /pass1.c (inode #14, mod time Tue Sep 21 04:28:37 1993)
|
||||
File /termcap (inode #12, mod time Tue Sep 21 03:19:14 1993)
|
||||
has 2 duplicate block(s), shared with 1 file(s):
|
||||
/motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
|
||||
Clone duplicate/bad blocks? yes
|
||||
|
@ -21,7 +21,7 @@ File /motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
|
|||
/termcap (inode #12, mod time Tue Sep 21 03:19:14 1993)
|
||||
Clone duplicate/bad blocks? yes
|
||||
|
||||
File /termcap (inode #12, mod time Tue Sep 21 03:19:14 1993)
|
||||
File /pass1.c (inode #14, mod time Tue Sep 21 04:28:37 1993)
|
||||
has 2 duplicate block(s), shared with 1 file(s):
|
||||
/motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
|
||||
Duplicated blocks already reassigned or cloned.
|
||||
|
|
|
@ -10,7 +10,7 @@ Pass 1C: Scan directories for inodes with dup blocks.
|
|||
Pass 1D: Reconciling duplicate blocks
|
||||
(There are 3 inodes containing duplicate/bad blocks.)
|
||||
|
||||
File /e2fsck (inode #16, mod time Tue Sep 21 04:32:22 1993)
|
||||
File /lost+found (inode #11, mod time Mon Sep 20 03:26:36 1993)
|
||||
has 2 duplicate block(s), shared with 0 file(s):
|
||||
Clone duplicate/bad blocks? yes
|
||||
|
||||
|
@ -18,7 +18,7 @@ File /pass1.c (inode #14, mod time Tue Sep 21 04:28:37 1993)
|
|||
has 2 duplicate block(s), shared with 0 file(s):
|
||||
Clone duplicate/bad blocks? yes
|
||||
|
||||
File /lost+found (inode #11, mod time Mon Sep 20 03:26:36 1993)
|
||||
File /e2fsck (inode #16, mod time Tue Sep 21 04:32:22 1993)
|
||||
has 2 duplicate block(s), shared with 0 file(s):
|
||||
Clone duplicate/bad blocks? yes
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ Pass 1C: Scan directories for inodes with dup blocks.
|
|||
Pass 1D: Reconciling duplicate blocks
|
||||
(There are 3 inodes containing duplicate/bad blocks.)
|
||||
|
||||
File /quux (inode #14, mod time Thu Aug 5 07:18:09 1999)
|
||||
has 1 duplicate block(s), shared with 2 file(s):
|
||||
File /foo (inode #12, mod time Thu Apr 28 17:57:53 1994)
|
||||
has 4 duplicate block(s), shared with 2 file(s):
|
||||
<filesystem metadata>
|
||||
/bar (inode #13, mod time Thu Aug 5 07:17:17 1999)
|
||||
Clone duplicate/bad blocks? yes
|
||||
|
@ -23,12 +23,12 @@ Clone duplicate/bad blocks? yes
|
|||
File /bar (inode #13, mod time Thu Aug 5 07:17:17 1999)
|
||||
has 2 duplicate block(s), shared with 3 file(s):
|
||||
<filesystem metadata>
|
||||
/quux (inode #14, mod time Thu Aug 5 07:18:09 1999)
|
||||
/foo (inode #12, mod time Thu Apr 28 17:57:53 1994)
|
||||
/quux (inode #14, mod time Thu Aug 5 07:18:09 1999)
|
||||
Clone duplicate/bad blocks? yes
|
||||
|
||||
File /foo (inode #12, mod time Thu Apr 28 17:57:53 1994)
|
||||
has 4 duplicate block(s), shared with 2 file(s):
|
||||
File /quux (inode #14, mod time Thu Aug 5 07:18:09 1999)
|
||||
has 1 duplicate block(s), shared with 2 file(s):
|
||||
<filesystem metadata>
|
||||
/bar (inode #13, mod time Thu Aug 5 07:17:17 1999)
|
||||
Clone duplicate/bad blocks? yes
|
||||
|
|
|
@ -3,5 +3,5 @@ Pass 2: Checking directory structure
|
|||
Pass 3: Checking directory connectivity
|
||||
Pass 4: Checking reference counts
|
||||
Pass 5: Checking group summary information
|
||||
test_filesys: 14/32 files (7.1% non-contiguous), 30/100 blocks
|
||||
test_filesys: 14/32 files (0.0% non-contiguous), 30/100 blocks
|
||||
Exit status is 0
|
||||
|
|
Loading…
Reference in New Issue