static ino_t lost_and_found = 0;
static int bad_lost_and_found = 0;
-static ext2fs_inode_bitmap inode_loop_detect;
-static ext2fs_inode_bitmap inode_done_map;
+static ext2fs_inode_bitmap inode_loop_detect = 0;
+static ext2fs_inode_bitmap inode_done_map = 0;
void e2fsck_pass3(e2fsck_t ctx)
{
#endif
struct problem_context pctx;
struct dir_info *dir;
- unsigned long max, count;
+ unsigned long maxdirs, count;
#ifdef RESOURCE_TRACK
init_resource_track(&rtrack);
pctx.num = 1;
fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
ctx->flags |= E2F_FLAG_ABORT;
- return;
+ goto abort_exit;
}
pctx.errcode = ext2fs_allocate_inode_bitmap(fs, "inode done bitmap",
&inode_done_map);
pctx.num = 2;
fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
ctx->flags |= E2F_FLAG_ABORT;
- return;
+ goto abort_exit;
}
#ifdef RESOURCE_TRACK
- if (ctx->options & E2F_OPT_TIME)
+ if (ctx->options & E2F_OPT_TIME) {
+ e2fsck_clear_progbar(ctx);
print_resource_track("Peak memory", &ctx->global_rtrack);
+ }
#endif
check_root(ctx);
- if (ctx->flags & E2F_FLAG_ABORT)
- return;
+ if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+ goto abort_exit;
ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
- max = e2fsck_get_num_dirinfo(ctx);
- count = 0;
+ maxdirs = e2fsck_get_num_dirinfo(ctx);
+ count = 1;
if (ctx->progress)
- (ctx->progress)(ctx, 3, 0, max);
+ if ((ctx->progress)(ctx, 3, 0, maxdirs))
+ goto abort_exit;
+
for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
if (ctx->progress)
- (ctx->progress)(ctx, 3, count++, max);
+ if ((ctx->progress)(ctx, 3, count++, maxdirs))
+ goto abort_exit;
if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
check_directory(ctx, dir, &pctx);
}
- if (ctx->progress)
- (ctx->progress)(ctx, 3, max, max);
-
+
+ /*
+ * Force the creation of /lost+found if not present
+ */
+ if ((ctx->flags & E2F_OPT_READONLY) == 0)
+ get_lost_and_found(ctx);
+
+abort_exit:
e2fsck_free_dir_info(ctx);
- ext2fs_free_inode_bitmap(inode_loop_detect);
- ext2fs_free_inode_bitmap(inode_done_map);
+ if (inode_loop_detect)
+ ext2fs_free_inode_bitmap(inode_loop_detect);
+ if (inode_done_map)
+ ext2fs_free_inode_bitmap(inode_done_map);
#ifdef RESOURCE_TRACK
- if (ctx->options & E2F_OPT_TIME2)
+ if (ctx->options & E2F_OPT_TIME2) {
+ e2fsck_clear_progbar(ctx);
print_resource_track("Pass 3", &rtrack);
+ }
#endif
}
ext2_filsys fs = ctx->fs;
struct dir_info *p = dir;
+ if (!p)
+ return;
+
ext2fs_clear_inode_bitmap(inode_loop_detect);
- while (p) {
- /*
- * If we find a parent which we've already checked,
- * then stop; we know it's either already connected to
- * the directory tree, or it isn't but the user has
- * already told us he doesn't want us to reconnect the
- * disconnected subtree.
- */
- if (ext2fs_test_inode_bitmap(inode_done_map, p->ino))
- goto check_dot_dot;
+
+ /*
+ * Keep going until we find a parent which we've already
+ * checked. We know it's either already connected to the
+ * directory tree, or it isn't but the user has already told
+ * us he doesn't want us to reconnect the disconnected
+ * subtree.
+ */
+ while (!ext2fs_test_inode_bitmap(inode_done_map, p->ino)) {
/*
* Mark this inode as being "done"; by the time we
* return from this function, the inode we either be
* lost+found.
*/
ext2fs_mark_inode_bitmap(inode_done_map, p->ino);
+
/*
* If this directory doesn't have a parent, or we've
* seen the parent once already, then offer to
*/
if (!p->parent ||
(ext2fs_test_inode_bitmap(inode_loop_detect,
- p->parent)))
+ p->parent))) {
+ pctx->ino = p->ino;
+ if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
+ if (e2fsck_reconnect_file(ctx, p->ino))
+ ext2fs_unmark_valid(fs);
+ else {
+ p->parent = lost_and_found;
+ fix_dotdot(ctx, p, lost_and_found);
+ }
+ }
break;
+ }
ext2fs_mark_inode_bitmap(inode_loop_detect,
p->parent);
+ pctx->ino = p->parent;
p = e2fsck_get_dir_info(ctx, p->parent);
- }
- /*
- * If we've reached here, we've hit a detached directory
- * inode; offer to reconnect it to lost+found.
- */
- pctx->ino = p->ino;
- if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
- if (e2fsck_reconnect_file(ctx, p->ino))
- ext2fs_unmark_valid(fs);
- else {
- p->parent = lost_and_found;
- fix_dotdot(ctx, p, lost_and_found);
+ if (!p) {
+ fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
+ return;
}
}
* Make sure that .. and the parent directory are the same;
* offer to fix it if not.
*/
-check_dot_dot:
if (dir->parent != dir->dotdot) {
pctx->ino = dir->ino;
pctx->ino2 = dir->dotdot;
char * block;
const char name[] = "lost+found";
struct problem_context pctx;
+ struct dir_info *dirinfo;
clear_problem_context(&pctx);
retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
sizeof(name)-1, 0, &ino);
- if (!retval)
- return ino;
- if (retval != EXT2_ET_FILE_NOT_FOUND) {
+ if (!retval) {
+ if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
+ return ino;
+ /* Lost+found isn't a directory! */
+ pctx.ino = ino;
+ if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
+ return 0;
+
+ /* OK, unlink the old /lost+found file. */
+ pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
+ if (pctx.errcode) {
+ pctx.str = "ext2fs_unlink";
+ fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
+ return 0;
+ }
+ dirinfo = e2fsck_get_dir_info(ctx, ino);
+ if (dirinfo)
+ dirinfo->parent = 0;
+ adjust_inode_count(ctx, ino, -1);
+ } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
pctx.errcode = retval;
fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
}
int offset,
int blocksize,
char *buf,
- void *private)
+ void *priv_data)
{
- struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) private;
+ struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
errcode_t retval;
struct problem_context pctx;
- if (dirent->name_len != 2)
+ if ((dirent->name_len & 0xFF) != 2)
return 0;
if (strncmp(dirent->name, "..", 2))
return 0;
static int expand_dir_proc(ext2_filsys fs,
blk_t *blocknr,
int blockcnt,
- void *private)
+ void *priv_data)
{
- struct expand_dir_struct *es = (struct expand_dir_struct *) private;
+ struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
blk_t new_blk;
static blk_t last_blk = 0;
char *block;
return BLOCK_ABORT;
}
es->done = 1;
+ retval = ext2fs_write_dir_block(fs, new_blk, block);
} else {
retval = ext2fs_get_mem(fs->blocksize, (void **) &block);
if (retval) {
return BLOCK_ABORT;
}
memset(block, 0, fs->blocksize);
+ retval = io_channel_write_blk(fs->io, new_blk, 1, block);
}
- retval = ext2fs_write_dir_block(fs, new_blk, block);
if (retval) {
es->err = retval;
return BLOCK_ABORT;
if (!(fs->flags & EXT2_FLAG_RW))
return EXT2_ET_RO_FILSYS;
+ /*
+ * Read the inode and block bitmaps in; we'll be messing with
+ * them.
+ */
+ e2fsck_read_bitmaps(ctx);
+
retval = ext2fs_check_directory(fs, dir);
if (retval)
return retval;