Many files:

Checked in e2fsprogs 1.08.
bitmap-optimize
Theodore Ts'o 1997-04-29 17:48:10 +00:00
parent 24757fa046
commit 521e368572
69 changed files with 1978 additions and 379 deletions

View File

@ -1,3 +1,8 @@
Thu Apr 10 14:36:05 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* ls.c: New file which implements the ls command. Added the -l
option.
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
* Release of E2fsprogs version 1.07

View File

@ -16,9 +16,9 @@ MANPAGES= debugfs.8
MK_CMDS= ../lib/ss/mk_cmds
DEBUG_OBJS= debug_cmds.o debugfs.o util.o ncheck.o icheck.o lsdel.o dump.o
DEBUG_OBJS= debug_cmds.o debugfs.o util.o ncheck.o icheck.o ls.o lsdel.o dump.o
SRCS= debug_cmds.c $(srcdir)/debugfs.c $(srcdir)/util.c \
SRCS= debug_cmds.c $(srcdir)/debugfs.c $(srcdir)/util.c $(srcdir)/ls.c \
$(srcdir)/ncheck.c $(srcdir)/icheck.c $(srcdir)/lsdel.c \
$(srcdir)/dump.c

View File

@ -150,7 +150,7 @@ which is a link to
.IR filespec .
Note this does not adjust the inode reference counts.
.TP
.I ls filespec
.I ls [-l] filespec
Print a listing of the files in the directory
.IR filespec .
.TP

View File

@ -727,78 +727,6 @@ void do_modify_inode(int argc, char *argv[])
}
}
/*
* list directory
*/
struct list_dir_struct {
FILE *f;
int col;
};
static int list_dir_proc(struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *private)
{
char name[EXT2_NAME_LEN];
char tmp[EXT2_NAME_LEN + 16];
struct list_dir_struct *ls = (struct list_dir_struct *) private;
int thislen;
thislen = (dirent->name_len < EXT2_NAME_LEN) ? dirent->name_len :
EXT2_NAME_LEN;
strncpy(name, dirent->name, thislen);
name[thislen] = '\0';
sprintf(tmp, "%d (%d) %s ", dirent->inode, dirent->rec_len, name);
thislen = strlen(tmp);
if (ls->col + thislen > 80) {
fprintf(ls->f, "\n");
ls->col = 0;
}
fprintf(ls->f, "%s", tmp);
ls->col += thislen;
return 0;
}
void do_list_dir(int argc, char *argv[])
{
ino_t inode;
int retval;
struct list_dir_struct ls;
if (argc > 2) {
com_err(argv[0], 0, "Usage: list_dir [pathname]");
return;
}
if (check_fs_open(argv[0]))
return;
if (argc == 2)
inode = string_to_inode(argv[1]);
else
inode = cwd;
if (!inode)
return;
ls.f = open_pager();
ls.col = 0;
retval = ext2fs_dir_iterate(current_fs, inode,
DIRENT_FLAG_INCLUDE_EMPTY,
0, list_dir_proc, &ls);
fprintf(ls.f, "\n");
close_pager(ls.f);
if (retval)
com_err(argv[1], retval, "");
return;
}
void do_change_working_dir(int argc, char *argv[])
{
ino_t inode;
@ -1337,6 +1265,7 @@ static void kill_file_by_inode(ino_t inode)
printf("Kill file by inode %ld\n", inode);
ext2fs_block_iterate(current_fs, inode, 0, NULL,
release_blocks_proc, NULL);
printf("\n");
ext2fs_unmark_inode_bitmap(current_fs->inode_map, inode);
ext2fs_mark_bb_dirty(current_fs);
@ -1479,7 +1408,7 @@ void main(int argc, char **argv)
{
int retval;
int sci_idx;
const char *usage = "Usage: debugfs [-w] [device]";
const char *usage = "Usage: debugfs [[-w] device]";
char c;
int open_flags = 0;
char *request = 0;

137
debugfs/ls.c Normal file
View File

@ -0,0 +1,137 @@
/*
* ls.c --- list directories
*
* Copyright (C) 1997 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include <sys/types.h>
#include "debugfs.h"
/*
* list directory
*/
#define LONG_OPT 0x0001
struct list_dir_struct {
FILE *f;
int col;
int options;
};
static const char *monstr[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
static void ls_l_file(struct list_dir_struct *ls, char *name, ino_t ino)
{
struct ext2_inode inode;
errcode_t retval;
struct tm *tm_p;
time_t modtime;
char datestr[80];
retval = ext2fs_read_inode(current_fs, ino, &inode);
if (retval) {
fprintf(ls->f, "%5d --- error --- %s\n", name);
return;
}
modtime = inode.i_mtime;
tm_p = localtime(&modtime);
sprintf(datestr, "%2d-%s-%2d %02d:%02d",
tm_p->tm_mday, monstr[tm_p->tm_mon], tm_p->tm_year,
tm_p->tm_hour, tm_p->tm_min);
fprintf(ls->f, "%6d %6o %5d %5d %5d %s %s\n", ino, inode.i_mode,
inode.i_uid, inode.i_gid, inode.i_size, datestr, name);
}
static void ls_file(struct list_dir_struct *ls, char *name,
ino_t ino, int rec_len)
{
char tmp[EXT2_NAME_LEN + 16];
int thislen;
sprintf(tmp, "%d (%d) %s ", ino, rec_len, name);
thislen = strlen(tmp);
if (ls->col + thislen > 80) {
fprintf(ls->f, "\n");
ls->col = 0;
}
fprintf(ls->f, "%s", tmp);
ls->col += thislen;
}
static int list_dir_proc(struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *private)
{
char name[EXT2_NAME_LEN];
char tmp[EXT2_NAME_LEN + 16];
struct list_dir_struct *ls = (struct list_dir_struct *) private;
int thislen;
thislen = (dirent->name_len < EXT2_NAME_LEN) ? dirent->name_len :
EXT2_NAME_LEN;
strncpy(name, dirent->name, thislen);
name[thislen] = '\0';
if (ls->options & LONG_OPT)
ls_l_file(ls, name, dirent->inode);
else
ls_file(ls, name, dirent->inode, dirent->rec_len);
return 0;
}
void do_list_dir(int argc, char *argv[])
{
ino_t inode;
int retval;
struct list_dir_struct ls;
int argptr = 1;
ls.options = 0;
if (check_fs_open(argv[0]))
return;
if ((argc > argptr) && (argv[argptr][0] == '-')) {
argptr++;
ls.options = LONG_OPT;
}
if (argc <= argptr)
inode = cwd;
else
inode = string_to_inode(argv[argptr]);
if (!inode)
return;
ls.f = open_pager();
ls.col = 0;
retval = ext2fs_dir_iterate(current_fs, inode,
DIRENT_FLAG_INCLUDE_EMPTY,
0, list_dir_proc, &ls);
fprintf(ls.f, "\n");
close_pager(ls.f);
if (retval)
com_err(argv[1], retval, "");
return;
}

View File

@ -1,7 +1,7 @@
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename libext2fs.info
@settitle The EXT2FS Library (version 1.07)
@settitle The EXT2FS Library (version 1.08)
@synindex tp fn
@comment %**end of header
@ -60,8 +60,8 @@ by the author.
@title The EXT2FS Library
@subtitle The EXT2FS Library
@subtitle Version 1.07
@subtitle February 1997
@subtitle Version 1.08
@subtitle April 1997
@author by Theodore Ts'o
@ -101,7 +101,7 @@ by the Foundation.
@top The EXT2FS Library
This manual documents the EXT2FS Library, version 1.07.
This manual documents the EXT2FS Library, version 1.08.
@end ifinfo
@ -130,8 +130,7 @@ manipulate an ext2 filesystem.
* Inode Functions::
* Directory functions::
* Bitmap Functions::
* Badblocks list management::
* Directory-block list management::
* EXT2 data abstractions::
* Byte-swapping functions::
* Other functions::
@end menu
@ -505,9 +504,21 @@ EXT2_ET_MISSING_INODE_TABLE.
@subsection Convenience functions for Inodes
@deftypefun errcode_t ext2fs_get_blocks (ext2_filsys @var{fs}, ino_t @var{ino}, blk_t *@var{blocks})
Returns an array of blocks corresponding to the direct,
indirect, doubly indirect, and triply indirect blocks as stored in the
inode structure.
@end deftypefun
@deftypefun errcode_t ext2fs_check_directory (ext2_filsys @var{fs}, ino_t @var{ino})
Returns 0 if @var{ino} is a directory, and @code{ENOTDIR} if it is not.
@end deftypefun
@deftypefun int ext2_inode_has_valid_blocks (struct ext2_inode *@var{inode})
Returns 1 if the inode's block entries actually valid block entries, and
0 if not. Inodes which represent devices and fast symbolic links do not
contain valid block entries.
@end deftypefun
@c ----------------------------------------------------------------------
@ -603,7 +614,7 @@ EXT2_ET_MISSING_INODE_TABLE.
@c ----------------------------------------------------------------------
@node Bitmap Functions, Badblocks list management, Directory functions, EXT2FS Library Functions
@node Bitmap Functions, EXT2 data abstractions, Directory functions, EXT2FS Library Functions
@comment node-name, next, previous, up
@section Bitmap Functions
@ -786,9 +797,24 @@ Return the first inode or block which is stored in the bitmap.
@c ----------------------------------------------------------------------
@node Badblocks list management, Directory-block list management, Bitmap Functions, EXT2FS Library Functions
@node EXT2 data abstractions, Byte-swapping functions, Bitmap Functions, EXT2FS Library Functions
@comment node-name, next, previous, up
@section Badblocks list management
@section EXT2 data abstractions
The ext2 library has a number of abstractions which are useful for ext2
utility programs.
@menu
* Badblocks list management::
* Directory-block list management::
* Inode count functions::
@end menu
@c ----------------------------------------------------------------------
@node Badblocks list management, Directory-block list management, EXT2 data abstractions, EXT2 data abstractions
@comment node-name, next, previous, up
@subsection Badblocks list management
@deftypefun errcode_t ext2fs_badblocks_list_create (ext2_badblocks_list *@var{ret}, int @var{size})
@ -824,29 +850,130 @@ Return the first inode or block which is stored in the bitmap.
@c ----------------------------------------------------------------------
@node Directory-block list management, Byte-swapping functions, Badblocks list management, EXT2FS Library Functions
@node Directory-block list management, Inode count functions, Badblocks list management, EXT2 data abstractions
@comment node-name, next, previous, up
@section Directory-block list management
@subsection Directory-block list management
The dblist abstraction stores a list of blocks belonging to
directories. This list can be useful when a program needs to interate
over all directory entries in a filesystem; @code{e2fsck} does this in
pass 2 of its operations, and @code{debugfs} needs to do this when it is
trying to turn an inode number into a pathname.
@deftypefun errcode_t ext2fs_init_dblist (ext2_filsys @var{fs}, ext2_dblist *@var{ret_dblist})
Creates a dblist data structure and return it in @var{ret_dblist}.
@end deftypefun
@deftypefun void ext2fs_free_dblist (ext2_dblist @var{dblist})
Free a dblist data structure.
@end deftypefun
@deftypefun errcode_t ext2fs_add_dir_block (ext2_dblist dblist, ino_t @var{ino}, blk_t @var{blk}, int @var{blockcnt})
@deftypefun errcode_t ext2fs_add_dir_block (ext2_dblist @var{dblist}, ino_t @var{ino}, blk_t @var{blk}, int @var{blockcnt})
Add an entry to the dblist data structure. This call records the fact
that block number @var{blockcnt} of directory inode @var{ino} is stored
in block @var{blk}.
@end deftypefun
@deftypefun errcode_t ext2fs_dblist_iterate (ext2_dblist dblist, int (*func)(ext2_filsys @var{fs}, struct ext2_db_entry *@var{db_info}, void *@var{private}), void *@var{private})
@deftypefun errcode_t ext2fs_set_dir_block (ext2_dblist @var{dblist}, ino_t @var{ino}, blk_t @var{blk}, int @var{blockcnt})
Change an entry in the dblist data structure; this changes the location
of block number @var{blockcnt} of directory indoe @var{ino} to be block
@var{blk}.
@end deftypefun
@deftypefun errcode_t ext2fs_dblist_dir_iterate
(ext2_dblist dblist, int flags, char *@var{block_buf}, int (*func)(ino_t @var{dir}, int @var{entry}, struct ext2_dir_entry *@var{dirent}, int @var{offset}, int @var{blocksize}, char *@var{buf}, void *@var{private}), void *@var{private})
@deftypefun errcode_t ext2fs_dblist_iterate (ext2_dblist @var{dblist}, int (*func)(ext2_filsys @var{fs}, struct ext2_db_entry *@var{db_info}, void *@var{private}), void *@var{private})
This iterator calls @var{func} for every entry in the dblist data structure.
@end deftypefun
@deftypefun errcode_t ext2fs_dblist_dir_iterate (ext2_dblist @var{dblist}, int flags, char *@var{block_buf}, int (*func)(ino_t @var{dir}, int @var{entry}, struct ext2_dir_entry *@var{dirent}, int @var{offset}, int @var{blocksize}, char *@var{buf}, void *@var{private}), void *@var{private})
This iterator takes reads in the directory block indicated in each
dblist entry, and calls @var{func} for each directory entry in each
directory block. If @var{dblist} contains all the directory blocks in a
filesystem, this function provides a convenient way to iterate over all
directory entries for that filesystem.
@end deftypefun
@c ----------------------------------------------------------------------
@node Byte-swapping functions, Other functions, Directory-block list management, EXT2FS Library Functions
@node Inode count functions, , Directory-block list management, EXT2 data abstractions
@comment node-name, next, previous, up
@subsection Inode count functions
The icount abstraction is a specialized data type used by @code{e2fsck}
to store how many times a particular inode is referenced by the
filesystem. This is used twice; once to store the actual number of times
that the inode is reference; and once to store the claimed number of times
the inode is referenced according to the inode structure.
This abstraction is designed to be extremely efficient for storing this
sort of information, by taking advantage of the following properties of
inode counts, namely (1) inode counts are very often zero (because
the inode is currrently not in use), and (2) many files have a inode
count of 1 (because they are a file which has no additional hard links).
@deftypefun errcode_t ext2fs_create_icount2(ext2_filsys @var{fs}, int @var{flags}, int @var{size}, ext2_icount_t @var{hint}, ext2_icount_t *@var{ret})
Creates an icount stucture for a filesystem @var{fs}, with initial space
for @var{size} inodes whose count is greater than 1. The @var{flags}
parameter is either 0 or @code{EXT2_ICOUNT_OPT_INCREMENT}, which
indicates that icount structure should be able to increment inode counts
quickly. The icount structure is returned in @var{ret}. The returned
icount structure initially has a count of zero for all inodes.
The @var{hint} parameter allows the caller to optionally pass in another
icount structure which is used to initialize the array of inodes whose
count is greater than 1. It is used purely as a speed optimization so
that the icount structure can determine in advance which inodes are
likely to contain a count grater than 1.
@end deftypefun
@deftypefun void ext2fs_free_icount(ext2_icount_t @var{icount})
Frees an icount structure.
@end deftypefun
@deftypefun errcode_t ext2fs_icount_fetch(ext2_icount_t @var{icount}, ino_t @var{ino}, __u16 *@var{ret})
Returns in @var{ret} fetches the count for a particular inode @var{ino}.
@end deftypefun
@deftypefun errcode_t ext2fs_icount_increment(ext2_icount_t @var{icount}, ino_t @var{ino}, __u16 *@var{ret})
Increments the ref count for inode @var{ino}.
@end deftypefun
@deftypefun errcode_t ext2fs_icount_decrement(ext2_icount_t @var{icount}, ino_t @var{ino}, __u16 *@var{ret})
Decrements the ref count for inode @var{ino}.
@end deftypefun
@deftypefun errcode_t ext2fs_icount_store(ext2_icount_t @var{icount}, ino_t @var{ino}, __u16 @var{count})
Sets the reference count for inode @var{ino} to be @var{count}.
@end deftypefun
@deftypefun ino_t ext2fs_get_icount_size(ext2_icount_t @var{icount})
Returns the current number of inodes in @var{icount} which has a count
greater than 1.
@end deftypefun
@deftypefun errcode_t ext2fs_icount_validate(ext2_icount_t @var{icount}, FILE *@var{f})
Validates the internal rep invariant of @var{icount}; if there are any
problems, print out debugging information to @var{f}. This function is
intended for debugging and testing use only.
@end deftypefun
@c ----------------------------------------------------------------------
@node Byte-swapping functions, Other functions, EXT2 data abstractions, EXT2FS Library Functions
@comment node-name, next, previous, up
@section Byte-swapping functions
@ -896,11 +1023,29 @@ Return the first inode or block which is stored in the bitmap.
@deftypefun errcode_t ext2fs_check_if_mounted (const char *@var{file}, int *@var{mount_flags})
@end deftypefun
/* version.c */
/* valid_blk.c */
@deftypefun int ext2_inode_has_valid_blocks (struct ext2_inode *@var{inode})
@deftypefun int ext2fs_get_library_version(const char **@var{ver_string}, const char **@var{date_string})
This function returns the current version of the ext2 library. The
return value contains an integer version code, which consists of the
major version number of the library multiplied by 100, plus the minor
version number of the library. Hence, if the library version is 1.08,
the returned value will be 108.
If @var{ver_string} and/or @var{date_string} are non-NULL, they will be
set to point at a constant string containing the library version and/or
release date, respectively.
@end deftypefun
@deftypefun int ext2fs_parse_version_string(const char *@var{ver_string})
This function takes a version string which may included in an
application and returns a version code using the same algorithm used by
@code{ext2fs_get_library_version}. It can be used by programs included
in the @code{e2fsprogs} distribution to assure that they are using an
up-to-date ext2 shared library.
@end deftypefun
/* inline functions */
@deftypefun int ext2fs_group_of_blk (ext2_filsys @var{fs}, blk_t @var{blk})

View File

@ -1,3 +1,38 @@
Thu Apr 10 13:51:16 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* pass1b.c (clone_file_block): If we clone a directory, we need to
update the dblist entry so that we check (and correct) the
right directory block.
Sun Apr 6 09:13:12 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* pass1.c (process_block): Don't clear blocks references to
filesystem metadata; let pass 1B handle this case.
* problem.c, problem.h: Add new problem, PR_1B_SHARE_METADATA.
* pass1b.c (pass1d): Deal with a block which is shared with
filesystem metadata.
* e2fsck.h: Make block_illegal_map be a global variable
Sat Apr 5 11:51:58 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* e2fsck.c, pass1.c (mark_table_blocks): Support the sparse_super
feature.
(get_backup_sb): New function which attempts to obtain the
correct backup superblock (if possible).
Fri Apr 4 10:46:26 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* e2fsck.c (main): Check the version of the library, and warn if
the library is out of date; this happens generally due to
users who manually install e2fsprogs.
* pass1.c (pass1_get_blocks): If the passed in inode number for
get_blocks isn't what we're expecting pass back
EXT2_ET_CALLBACK_NOT_HANDLED.
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
* Release of E2fsprogs version 1.07

View File

@ -216,6 +216,13 @@ static void sync_disks(NOARGS)
sync();
}
static blk_t get_backup_sb(ext2_filsys fs)
{
if (!fs || !fs->super)
return 8193;
return fs->super->s_blocks_per_group + 1;
}
#define MIN_CHECK 1
#define MAX_CHECK 2
@ -224,21 +231,22 @@ static const char *corrupt_msg =
"filesystem. If the device is valid and it really contains an ext2\n"
"filesystem (and not swap or ufs or something else), then the superblock\n"
"is corrupt, and you might try running e2fsck with an alternate superblock:\n"
" e2fsck -b 8193 <device>\n\n";
" e2fsck -b %d <device>\n\n";
static void check_super_value(const char *descr, unsigned long value,
int flags, unsigned long min, unsigned long max)
static void check_super_value(ext2_filsys fs, const char *descr,
unsigned long value, int flags,
unsigned long min, unsigned long max)
{
if (((flags & MIN_CHECK) && (value < min)) ||
((flags & MAX_CHECK) && (value > max))) {
printf("Corruption found in superblock. (%s = %lu).\n",
descr, value);
printf(corrupt_msg);
printf(corrupt_msg, get_backup_sb(fs));
fatal_error(0);
}
}
static void relocate_hint(void)
static void relocate_hint(ext2_filsys fs)
{
static hint_issued = 0;
@ -252,9 +260,9 @@ static void relocate_hint(void)
printf("Note: if there is several inode or block bitmap blocks\n"
"which require relocation, or one part of the inode table\n"
"which must be moved, you may wish to try running e2fsck\n"
"the '-b 8193' option first. The problem may lie only with\n"
"the primary block group descriptor, and the backup block\n"
"group descriptor may be OK.\n\n");
"with the '-b %d' option first. The problem may lie only\n"
"with the primary block group descriptor, and the backup\n"
"block group descriptor may be OK.\n\n", get_backup_sb(fs));
hint_issued = 1;
}
@ -274,24 +282,24 @@ static void check_super_block(ext2_filsys fs)
/*
* Verify the super block constants...
*/
check_super_value("inodes_count", s->s_inodes_count,
check_super_value(fs, "inodes_count", s->s_inodes_count,
MIN_CHECK, 1, 0);
check_super_value("blocks_count", s->s_blocks_count,
check_super_value(fs, "blocks_count", s->s_blocks_count,
MIN_CHECK, 1, 0);
check_super_value("first_data_block", s->s_first_data_block,
check_super_value(fs, "first_data_block", s->s_first_data_block,
MAX_CHECK, 0, s->s_blocks_count);
check_super_value("log_frag_size", s->s_log_frag_size,
check_super_value(fs, "log_frag_size", s->s_log_frag_size,
MAX_CHECK, 0, 2);
check_super_value("log_block_size", s->s_log_block_size,
check_super_value(fs, "log_block_size", s->s_log_block_size,
MIN_CHECK | MAX_CHECK, s->s_log_frag_size,
2);
check_super_value("frags_per_group", s->s_frags_per_group,
check_super_value(fs, "frags_per_group", s->s_frags_per_group,
MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s));
check_super_value("blocks_per_group", s->s_blocks_per_group,
check_super_value(fs, "blocks_per_group", s->s_blocks_per_group,
MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s));
check_super_value("inodes_per_group", s->s_inodes_per_group,
check_super_value(fs, "inodes_per_group", s->s_inodes_per_group,
MIN_CHECK, 1, 0);
check_super_value("r_blocks_count", s->s_r_blocks_count,
check_super_value(fs, "r_blocks_count", s->s_r_blocks_count,
MAX_CHECK, 0, s->s_blocks_count);
retval = ext2fs_get_device_size(filesystem_name, EXT2_BLOCK_SIZE(s),
@ -326,7 +334,7 @@ static void check_super_block(ext2_filsys fs)
printf("Superblock blocks_per_group = %u, should "
"have been %u\n", s->s_blocks_per_group,
should_be);
printf(corrupt_msg);
printf(corrupt_msg, get_backup_sb(fs));
fatal_error(0);
}
@ -335,7 +343,7 @@ static void check_super_block(ext2_filsys fs)
printf("Superblock first_data_block = %u, should "
"have been %u\n", s->s_first_data_block,
should_be);
printf(corrupt_msg);
printf(corrupt_msg, get_backup_sb(fs));
fatal_error(0);
}
@ -352,7 +360,7 @@ static void check_super_block(ext2_filsys fs)
last_block = fs->super->s_blocks_count;
if ((fs->group_desc[i].bg_block_bitmap < first_block) ||
(fs->group_desc[i].bg_block_bitmap >= last_block)) {
relocate_hint();
relocate_hint(fs);
pctx.blk = fs->group_desc[i].bg_block_bitmap;
if (fix_problem(fs, PR_0_BB_NOT_GROUP, &pctx)) {
fs->group_desc[i].bg_block_bitmap = 0;
@ -362,7 +370,7 @@ static void check_super_block(ext2_filsys fs)
}
if ((fs->group_desc[i].bg_inode_bitmap < first_block) ||
(fs->group_desc[i].bg_inode_bitmap >= last_block)) {
relocate_hint();
relocate_hint(fs);
pctx.blk = fs->group_desc[i].bg_inode_bitmap;
if (fix_problem(fs, PR_0_IB_NOT_GROUP, &pctx)) {
fs->group_desc[i].bg_inode_bitmap = 0;
@ -373,7 +381,7 @@ static void check_super_block(ext2_filsys fs)
if ((fs->group_desc[i].bg_inode_table < first_block) ||
((fs->group_desc[i].bg_inode_table +
fs->inode_blocks_per_group - 1) >= last_block)) {
relocate_hint();
relocate_hint(fs);
pctx.blk = fs->group_desc[i].bg_inode_table;
if (fix_problem(fs, PR_0_ITABLE_NOT_GROUP, &pctx)) {
fs->group_desc[i].bg_inode_table = 0;
@ -591,6 +599,9 @@ static void PRS(int argc, char *argv[])
}
}
}
static const char *my_ver_string = E2FSPROGS_VERSION;
static const char *my_ver_date = E2FSPROGS_DATE;
int main (int argc, char *argv[])
{
@ -600,6 +611,8 @@ int main (int argc, char *argv[])
ext2_filsys fs = 0;
io_manager io_ptr;
struct ext2fs_sb *s;
const char *lib_ver_date;
int my_ver, lib_ver;
#ifdef MTRACE
mtrace();
@ -607,6 +620,13 @@ int main (int argc, char *argv[])
#ifdef MCHECK
mcheck(0);
#endif
my_ver = ext2fs_parse_version_string(my_ver_string);
lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
if (my_ver > lib_ver) {
fprintf( stderr, "Error: ext2fs library version "
"out of date!\n");
show_version_only++;
}
init_resource_track(&global_rtrack);
@ -614,12 +634,12 @@ int main (int argc, char *argv[])
if (!preen || show_version_only)
fprintf (stderr, "e2fsck %s, %s for EXT2 FS %s, %s\n",
E2FSPROGS_VERSION, E2FSPROGS_DATE,
EXT2FS_VERSION, EXT2FS_DATE);
my_ver_string, my_ver_date, EXT2FS_VERSION,
EXT2FS_DATE);
if (show_version_only) {
fprintf(stderr, "\tUsing %s\n",
error_message(EXT2_ET_BASE));
fprintf(stderr, "\tUsing %s, %s\n",
error_message(EXT2_ET_BASE), lib_ver_date);
exit(0);
}
@ -663,7 +683,7 @@ restart:
printf("%s trying backup blocks...\n",
retval ? "Couldn't find ext2 superblock," :
"Group descriptors look bad...");
superblock = 8193;
superblock = get_backup_sb(fs);
if (fs)
ext2fs_close(fs);
goto restart;
@ -683,7 +703,7 @@ restart:
else if (retval == ENXIO)
printf("Possibly non-existent or swap device?\n");
else
printf(corrupt_msg);
printf(corrupt_msg, get_backup_sb(fs));
fatal_error(0);
}
#ifdef EXT2_CURRENT_REV
@ -695,18 +715,23 @@ restart:
}
#endif
/*
* Check for compatibility with the feature sets. We have to
* check because we need to be more stringent than ext2fs_open
* Check for compatibility with the feature sets. We need to
* be more stringent than ext2fs_open().
*/
s = (struct ext2fs_sb *) fs->super;
if (s->s_feature_compat || s->s_feature_incompat ||
s->s_feature_ro_compat) {
if ((s->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
(s->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
com_err(program_name, EXT2_ET_UNSUPP_FEATURE,
" (%s)", filesystem_name);
"(%s)", filesystem_name);
get_newer:
printf ("Get a newer version of e2fsck!\n");
fatal_error(0);
}
if (s->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
com_err(program_name, EXT2_ET_RO_UNSUPP_FEATURE,
"(%s)", filesystem_name);
goto get_newer;
}
/*
* If the user specified a specific superblock, presumably the

View File

@ -85,6 +85,7 @@ extern ext2fs_inode_bitmap inode_bb_map; /* Inodes which are in bad blocks */
extern ext2fs_block_bitmap block_found_map; /* Blocks which are in use */
extern ext2fs_block_bitmap block_dup_map; /* Blocks which are used by more than once */
extern ext2fs_block_bitmap block_illegal_map; /* Meta-data blocks */
extern const char *fix_msg[2]; /* Fixed or ignored! */
extern const char *clear_msg[2]; /* Cleared or ignored! */

View File

@ -217,7 +217,7 @@ void pass1(ext2_filsys fs)
"while allocating block_illegal_map");
fatal_error(0);
}
retval = ext2fs_create_icount(fs, 0, 0, &inode_link_info);
retval = ext2fs_create_icount2(fs, 0, 0, 0, &inode_link_info);
if (retval) {
com_err("ext2fs_create_icount", retval,
"while creating inode_link_info");
@ -821,8 +821,11 @@ int process_block(ext2_filsys fs,
if (blk < fs->super->s_first_data_block ||
blk >= fs->super->s_blocks_count)
problem = PR_1_ILLEGAL_BLOCK_NUM;
else if (ext2fs_test_block_bitmap(block_illegal_map, blk))
problem = PR_1_BLOCK_OVERLAPS_METADATA;
#if 0
else
if (ext2fs_test_block_bitmap(block_illegal_map, blk))
problem = PR_1_BLOCK_OVERLAPS_METADATA;
#endif
if (problem) {
p->num_illegal_blocks++;
@ -1184,21 +1187,23 @@ static void mark_table_blocks(ext2_filsys fs)
fs->group_desc[i].bg_inode_bitmap);
}
}
/*
* Mark this group's copy of the superblock
*/
ext2fs_mark_block_bitmap(block_found_map, block);
ext2fs_mark_block_bitmap(block_illegal_map, block);
if (ext2fs_bg_has_super(fs, i)) {
/*
* Mark this group's copy of the superblock
*/
ext2fs_mark_block_bitmap(block_found_map, block);
ext2fs_mark_block_bitmap(block_illegal_map, block);
/*
* Mark this group's copy of the descriptors
*/
for (j = 0; j < fs->desc_blocks; j++) {
ext2fs_mark_block_bitmap(block_found_map,
block + j + 1);
ext2fs_mark_block_bitmap(block_illegal_map,
block + j + 1);
/*
* Mark this group's copy of the descriptors
*/
for (j = 0; j < fs->desc_blocks; j++) {
ext2fs_mark_block_bitmap(block_found_map,
block + j + 1);
ext2fs_mark_block_bitmap(block_illegal_map,
block + j + 1);
}
}
block += fs->super->s_blocks_per_group;
}
@ -1214,15 +1219,12 @@ errcode_t pass1_get_blocks(ext2_filsys fs, ino_t ino, blk_t *blocks)
{
int i;
if (ino == stashed_ino) {
for (i=0; i < EXT2_N_BLOCKS; i++)
blocks[i] = stashed_inode->i_block[i];
return 0;
}
printf("INTERNAL ERROR: pass1_get_blocks: unexpected inode #%lu\n",
ino);
printf("\t(was expecting %lu)\n", stashed_ino);
exit(FSCK_ERROR);
if (ino != stashed_ino)
return EXT2_ET_CALLBACK_NOTHANDLED;
for (i=0; i < EXT2_N_BLOCKS; i++)
blocks[i] = stashed_inode->i_block[i];
return 0;
}
errcode_t pass1_read_inode(ext2_filsys fs, ino_t ino, struct ext2_inode *inode)

View File

@ -277,6 +277,7 @@ int process_pass1b_block(ext2_filsys fs,
struct search_dir_struct {
int count;
ino_t first_inode;
ino_t max_inode;
};
static int search_dirent_proc(ino_t dir, int entry,
@ -287,6 +288,10 @@ static int search_dirent_proc(ino_t dir, int entry,
struct search_dir_struct *sd = private;
struct dup_inode *p;
if (dirent->inode > sd->max_inode)
/* Should abort this inode, but not everything */
return 0;
if (!dirent->inode || (entry < DIRENT_OTHER_FILE) ||
!ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
return 0;
@ -332,6 +337,7 @@ void pass1c(ext2_filsys fs, char *block_buf)
*/
sd.count = inodes_left;
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,
search_dirent_proc, &sd);
}
@ -345,6 +351,7 @@ static void pass1d(ext2_filsys fs, char *block_buf)
int i;
errcode_t retval;
int file_ok;
int meta_data = 0;
struct problem_context pctx;
printf("Pass 1D: Reconciling duplicate blocks\n");
@ -376,6 +383,12 @@ static void pass1d(ext2_filsys fs, char *block_buf)
continue;
if (q->num_bad > 1)
file_ok = 0;
if (ext2fs_test_block_bitmap(block_illegal_map,
q->block)) {
file_ok = 0;
meta_data = 1;
}
/*
* Add all inodes used by this block to the
* shared[] --- which is a unique list, so
@ -402,11 +415,14 @@ static void pass1d(ext2_filsys fs, char *block_buf)
pctx.ino = p->ino;
pctx.dir = p->dir;
pctx.blkcount = p->num_dupblocks;
pctx.num = shared_len;
pctx.num = meta_data ? shared_len+1 : shared_len;
fix_problem(fs, PR_1B_DUP_FILE, &pctx);
pctx.blkcount = 0;
pctx.num = 0;
if (meta_data)
fix_problem(fs, PR_1B_SHARE_METADATA, &pctx);
for (i = 0; i < shared_len; i++) {
for (s = dup_ino; s; s = s->next)
if (s->ino == shared[i])
@ -506,6 +522,7 @@ static void delete_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf)
struct clone_struct {
errcode_t errcode;
ino_t dir;
char *buf;
};
@ -533,6 +550,14 @@ static int clone_file_block(ext2_filsys fs,
cs->errcode = retval;
return BLOCK_ABORT;
}
if (cs->dir) {
retval = ext2fs_set_dir_block(fs->dblist,
cs->dir, new_block, blockcnt);
if (retval) {
cs->errcode = retval;
return BLOCK_ABORT;
}
}
retval = io_channel_read_blk(fs->io, *block_nr, 1,
cs->buf);
if (retval) {
@ -569,8 +594,12 @@ static int clone_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf)
cs.errcode = 0;
cs.buf = malloc(fs->blocksize);
cs.dir = 0;
if (!cs.buf)
return ENOMEM;
if (ext2fs_test_inode_bitmap(inode_dir_map, dp->ino))
cs.dir = dp->ino;
retval = ext2fs_block_iterate(fs, dp->ino, 0, block_buf,
clone_file_block, &cs);

View File

@ -86,9 +86,8 @@ void pass2(ext2_filsys fs)
if (!preen)
printf("Pass 2: Checking directory structure\n");
size = ext2fs_get_icount_size(inode_link_info) + 10;
retval = ext2fs_create_icount(fs, EXT2_ICOUNT_OPT_INCREMENT,
size, &inode_count);
retval = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
0, inode_link_info, &inode_count);
if (retval) {
com_err("ext2fs_create_icount", retval,
"while creating inode_count");

View File

@ -191,6 +191,10 @@ static struct e2fsck_problem problem_table[] = {
"\t%Q (@i #%i, mod time %IM)\n",
PROMPT_FIX, PR_MSG_ONLY },
/* File sharing blocks with filesystem metadata */
{ PR_1B_SHARE_METADATA,
"\t<filesystem metadata>\n",
PROMPT_FIX, PR_MSG_ONLY },
/* Pass 2 errors */

View File

@ -125,6 +125,9 @@ struct e2fsck_problem {
/* List of files sharing duplicate blocks */
#define PR_1B_DUP_FILE_LIST 0x011002
/* File sharing blocks with filesystem metadata */
#define PR_1B_SHARE_METADATA 0x011003
/*
* Pass 2 errors
*/

View File

@ -38,6 +38,19 @@
#define EXT2FS_DATE "95/08/09"
#define EXT2FS_VERSION "0.5b"
/*
* Debug code
*/
#ifdef EXT2FS_DEBUG
# define ext2_debug(f, a...) { \
printk ("EXT2-fs DEBUG (%s, %d): %s:", \
__FILE__, __LINE__, __FUNCTION__); \
printk (f, ## a); \
}
#else
# define ext2_debug(f, a...) /**/
#endif
/*
* Special inodes numbers
*/
@ -47,7 +60,9 @@
#define EXT2_ACL_DATA_INO 4 /* ACL inode */
#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
#define EXT2_FIRST_INO 11 /* First non reserved inode */
/* First non-reserved inode for old ext2 filesystems */
#define EXT2_GOOD_OLD_FIRST_INO 11
/*
* The second extended file system magic number
@ -77,10 +92,17 @@
#else
# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
#endif
#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_inode))
#ifdef __KERNEL__
#define EXT2_ADDR_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_addr_per_block_bits)
#define EXT2_INODES_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_inodes_per_block_bits)
#define EXT2_INODE_SIZE(s) ((s)->u.ext2_sb.s_inode_size)
#define EXT2_FIRST_INO(s) ((s)->u.ext2_sb.s_first_ino)
#else
#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
EXT2_GOOD_OLD_INODE_SIZE : \
(s)->s_inode_size)
#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
EXT2_GOOD_OLD_FIRST_INO : \
(s)->s_first_ino)
#endif
/*
@ -167,7 +189,9 @@ struct ext2_group_desc
#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */
#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
/*
* ioctl commands
*/
@ -314,14 +338,36 @@ struct ext2_super_block {
__u16 s_magic; /* Magic signature */
__u16 s_state; /* File system state */
__u16 s_errors; /* Behaviour when detecting errors */
__u16 s_pad;
__u16 s_minor_rev_level; /* minor revision level */
__u32 s_lastcheck; /* time of last check */
__u32 s_checkinterval; /* max. time between checks */
__u32 s_creator_os; /* OS */
__u32 s_rev_level; /* Revision level */
__u16 s_def_resuid; /* Default uid for reserved blocks */
__u16 s_def_resgid; /* Default gid for reserved blocks */
__u32 s_reserved[235]; /* Padding to the end of the block */
/*
* These fields are for EXT2_DYNAMIC_REV superblocks only.
*
* Note: the difference between the compatible feature set and
* the incompatible feature set is that if there is a bit set
* in the incompatible feature set that the kernel doesn't
* know about, it should refuse to mount the filesystem.
*
* e2fsck's requirements are more strict; if it doesn't know
* about a feature in either the compatible or incompatible
* feature set, it must abort and not try to meddle with
* things it doesn't understand...
*/
__u32 s_first_ino; /* First non-reserved inode */
__u16 s_inode_size; /* size of inode structure */
__u16 s_block_group_nr; /* block group # of this superblock */
__u32 s_feature_compat; /* compatible feature set */
__u32 s_feature_incompat; /* incompatible feature set */
__u32 s_feature_ro_compat; /* readonly-compatible feature set */
__u8 s_uuid[16]; /* 128-bit uuid for volume */
char s_volume_name[16]; /* volume name */
char s_last_mounted[64]; /* directory where last mounted */
__u32 s_reserved[206]; /* Padding to the end of the block */
};
/*
@ -337,8 +383,22 @@ struct ext2_super_block {
* Revision levels
*/
#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV
#define EXT2_GOOD_OLD_INODE_SIZE 128
/*
* Feature set definitions
*/
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
#define EXT2_FEATURE_COMPAT_SUPP 0
#define EXT2_FEATURE_INCOMPAT_SUPP 0
#define EXT2_FEATURE_RO_COMPAT_SUPP EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
/*
* Default values for user and/or group using reserved blocks
@ -391,9 +451,9 @@ struct ext2_dir_entry {
extern int ext2_permission (struct inode *, int);
/* balloc.c */
extern int ext2_new_block (struct super_block *, unsigned long,
__u32 *, __u32 *);
extern void ext2_free_blocks (struct super_block *, unsigned long,
extern int ext2_new_block (const struct inode *, unsigned long,
__u32 *, __u32 *, int *);
extern void ext2_free_blocks (const struct inode *, unsigned long,
unsigned long);
extern unsigned long ext2_count_free_blocks (struct super_block *);
extern void ext2_check_blocks_bitmap (struct super_block *);
@ -414,7 +474,7 @@ extern int ext2_write (struct inode *, struct file *, char *, int);
extern int ext2_sync_file (struct inode *, struct file *);
/* ialloc.c */
extern struct inode * ext2_new_inode (const struct inode *, int);
extern struct inode * ext2_new_inode (const struct inode *, int, int *);
extern void ext2_free_inode (struct inode *);
extern unsigned long ext2_count_free_inodes (struct super_block *);
extern void ext2_check_inodes_bitmap (struct super_block *);
@ -448,7 +508,7 @@ extern int ext2_symlink (struct inode *, const char *, int, const char *);
extern int ext2_link (struct inode *, struct inode *, const char *, int);
extern int ext2_mknod (struct inode *, const char *, int, int, int);
extern int ext2_rename (struct inode *, const char *, int,
struct inode *, const char *, int);
struct inode *, const char *, int, int);
/* super.c */
extern void ext2_error (struct super_block *, const char *, const char *, ...)
@ -462,6 +522,7 @@ extern void ext2_put_super (struct super_block *);
extern void ext2_write_super (struct super_block *);
extern int ext2_remount (struct super_block *, int *, char *);
extern struct super_block * ext2_read_super (struct super_block *,void *,int);
extern int init_ext2_fs(void);
extern void ext2_statfs (struct super_block *, struct statfs *, int);
/* truncate.c */

View File

@ -1,3 +1,8 @@
Sat Apr 5 11:48:03 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* ls.c (list_super): Display the filesystem revision and any
features that might be implemented.
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
* Release of E2fsprogs version 1.07

View File

@ -34,13 +34,13 @@ LIBDIR= e2p
DLL_ADDRESS = 0x66980000
DLL_JUMPSIZE = 0x1000
DLL_GOTSIZE = 0x1000
DLL_VERSION = 1.2
DLL_VERSION = 1.3
DLL_IMAGE = libe2p
DLL_STUB = libe2p
DLL_MYDIR = e2p
DLL_INSTALL_DIR = $(libdir)
ELF_VERSION = 2.2
ELF_VERSION = 2.3
ELF_SO_VERSION = 2
ELF_IMAGE = libe2p
ELF_MYDIR = e2p

View File

@ -76,6 +76,10 @@ struct ext2fs_sb {
__u32 s_reserved[206]; /* Padding to the end of the block */
};
#ifndef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
#endif
static void print_user (unsigned short uid)
{
struct passwd *pw;
@ -164,8 +168,6 @@ void list_super (struct ext2_super_block * s)
EXT2_INODE_SIZE(s)) +
EXT2_BLOCK_SIZE(s) - 1) /
EXT2_BLOCK_SIZE(s));
printf ("Filesystem magic number: 0x%04X\n", s->s_magic);
printf ("Filesystem revision #: %d\n", s->s_rev_level);
if (sb->s_volume_name[0]) {
memset(buf, 0, sizeof(buf));
strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name));
@ -183,6 +185,22 @@ void list_super (struct ext2_super_block * s)
} else
strcpy(buf, "<none>");
printf("Filesystem UUID: %s\n", buf);
printf ("Filesystem magic number: 0x%04X\n", s->s_magic);
printf ("Filesystem revision #: %d", s->s_rev_level);
if (s->s_rev_level == EXT2_GOOD_OLD_REV) {
printf(" (original)\n");
#ifdef EXT2_DYNAMIC_REV
} else if (s->s_rev_level == EXT2_DYNAMIC_REV) {
printf(" (dynamic)\n");
#endif
} else
printf("\n");
printf ("Filesystem features: ");
if (s->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)
printf("sparse_super");
else
printf("(none)");
printf("\n");
printf ("Filesystem state: ");
print_fs_state (stdout, s->s_state);
printf ("\n");

View File

@ -1,3 +1,73 @@
Thu Apr 10 13:15:15 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* dblist.c (ext2fs_set_dir_block): New function which sets the
block of a dblist entry, given the directory inode and
blockcnt.
Sat Apr 5 12:42:42 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* alloc_tables.c (ext2fs_allocate_tables): Allocate the bitmap and
inode bitmaps at staggered locations across the block
groups, to avoid concentrating the bitmaps on a small
number of disks when using striped RAID arrays.
* initialize.c (ext2fs_initialize): By default, choose the maximum
possible number of blocks per group (based on the size of
the bitmaps in the blocksize).
Fri Apr 4 11:28:16 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* initialize.c (ext2fs_initialize): Add support for
EXT2_COMPAT_SPARSE_SUPER feature.
* closefs.c (ext2fs_bg_has_super): New function to determine
whether or a particular block group should have a
superblock and block group descriptor. Used for the
EXT2_COMPAT_SPARSE_SUPER feature is turned on.
(ext2fs_flush): Check ext2fs_bg_has_super to see whether
or not the superblock should be written out for the block
group.
* ext2fs.h (EXT2_COMPAT_SPARSE_SUPER): Define compatibility flag
for sparse duplicate superblocks.
* version.c (ext2fs_get_library_version): New function which
returns the library version.
* version.c (ext2fs_parse_version_string): New function which
parses a version string and returns a version number,
so application programs can compare version numbers as
integers.
Wed Mar 26 00:43:52 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* icount.c (ext2fs_create_icount): Change function so that it also
takes a new argument which contains a "hint" icount
structure. This "hint" icount allows the create function
to set up the sorted list in advance. This reduces
significantly the amount of data moving needed to insert
these inodes into the list later.
* icount.c (ext2fs_icount_validate): New function which validates
that the icount structure's rep invariant.
* icount.c (get_icount_el): Completely revamped implementation
to subsume put_icount_el(). Put_icount_el() used to
use an O(N) implementation to insert in the middle
of the icount list. It now uses a O(ln N) to search
for where the icount should be inserted, and then uses
a memcpy to move the list down (instead of a for loop).
* icount.c (ext2fs_icount_fetch, ext2fs_icount_store,
ext2fs_icount_increment, ext2fs_icount_decrement): Check
to see if the inode is within bounds; if it isn't, return
EINVAL.
* bitops.h (ext2fs_test_generic_bitmap): Fix error message given
when a bad inode number is passed to test_generic_bitmap
to be EXT2FS_TEST_ERROR instead of the wrong
EXT2FS_UNMARK_ERROR.
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
* Release of E2fsprogs version 1.07

View File

@ -50,7 +50,8 @@ OBJS= ext2_err.o \
test_io.o \
unix_io.o \
unlink.o \
valid_blk.o
valid_blk.o \
version.o
SRCS= ext2_err.c \
$(srcdir)/alloc.c \
@ -95,7 +96,8 @@ SRCS= ext2_err.c \
$(srcdir)/test_io.c \
$(srcdir)/unix_io.c \
$(srcdir)/unlink.c \
$(srcdir)/valid_blk.c
$(srcdir)/valid_blk.c \
$(srcdir)/version.c
HFILES= bitops.h ext2fs.h io.h
@ -105,21 +107,21 @@ LIBDIR= ext2fs
DLL_ADDRESS = 0x66900000
DLL_JUMPSIZE = 0x1000
DLL_GOTSIZE = 0x1000
DLL_VERSION = 1.1
DLL_VERSION = 1.2
DLL_IMAGE = libe2fs
DLL_STUB = libext2fs
DLL_LIBS = -L../.. -lcom_err
DLL_MYDIR = ext2fs
DLL_INSTALL_DIR = $(libdir)
ELF_VERSION = 2.2
ELF_VERSION = 2.3
ELF_SO_VERSION = 2
ELF_IMAGE = libext2fs
ELF_MYDIR = ext2fs
ELF_INSTALL_DIR = $(libdir)
ELF_OTHER_LIBS = -lc -L../.. -lcom_err
BSDLIB_VERSION = 2.0
BSDLIB_VERSION = 2.1
BSDLIB_IMAGE = libext2fs
BSDLIB_MYDIR = ext2fs
BSDLIB_INSTALL_DIR = $(libdir)

View File

@ -29,37 +29,17 @@
errcode_t ext2fs_allocate_tables(ext2_filsys fs)
{
errcode_t retval;
blk_t group_blk, last_blk, new_blk, blk;
blk_t group_blk, start_blk, last_blk, new_blk, blk;
int i, j;
group_blk = fs->super->s_first_data_block;
for (i = 0; i < fs->group_desc_count; i++) {
last_blk = group_blk + fs->super->s_blocks_per_group;
/*
* Allocate the block bitmap
* Allocate the inode table
*/
retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
1, fs->block_map, &new_blk);
if (retval)
return retval;
ext2fs_mark_block_bitmap(fs->block_map, new_blk);
fs->group_desc[i].bg_block_bitmap = new_blk;
/*
* ... and the inode bitmap
*/
retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
1, fs->block_map, &new_blk);
if (retval)
return retval;
ext2fs_mark_block_bitmap(fs->block_map, new_blk);
fs->group_desc[i].bg_inode_bitmap = new_blk;
/*
* Finally, allocate the inode table
*/
retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
start_blk = group_blk + 3 + fs->desc_blocks;
retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
fs->inode_blocks_per_group,
fs->block_map, &new_blk);
if (retval)
@ -70,6 +50,25 @@ errcode_t ext2fs_allocate_tables(ext2_filsys fs)
ext2fs_mark_block_bitmap(fs->block_map, blk);
fs->group_desc[i].bg_inode_table = new_blk;
/*
* Allocate the block and inode bitmaps
*/
start_blk += fs->inode_blocks_per_group +
((2 * i) % (last_blk - start_blk));
retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
1, fs->block_map, &new_blk);
if (retval)
return retval;
ext2fs_mark_block_bitmap(fs->block_map, new_blk);
fs->group_desc[i].bg_block_bitmap = new_blk;
retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
1, fs->block_map, &new_blk);
if (retval)
return retval;
ext2fs_mark_block_bitmap(fs->block_map, new_blk);
fs->group_desc[i].bg_inode_bitmap = new_blk;
/*
* Increment the start of the block group
*/

View File

@ -353,7 +353,7 @@ _INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
blk_t bitno)
{
if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno);
return 0;
}
return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap);

View File

@ -22,6 +22,38 @@
#include "ext2fsP.h"
static int test_root(int a, int b)
{
if (a == 0)
return 1;
while (1) {
if (a == 1)
return 1;
if (a % b)
return 0;
a = a / b;
}
}
int ext2fs_bg_has_super(ext2_filsys fs, int group_block)
{
#ifdef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
struct ext2fs_sb *s;
s = (struct ext2fs_sb *) fs->super;
if (!(s->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
return 1;
if (test_root(group_block, 3) || (test_root(group_block, 5)) ||
test_root(group_block, 7))
return 1;
return 0;
#else
return 1;
#endif
}
errcode_t ext2fs_flush(ext2_filsys fs)
{
int i,j,maxgroup;
@ -92,6 +124,9 @@ errcode_t ext2fs_flush(ext2_filsys fs)
maxgroup = (fs->flags & EXT2_FLAG_MASTER_SB_ONLY) ? 1 :
fs->group_desc_count;
for (i = 0; i < maxgroup; i++) {
if (!ext2fs_bg_has_super(fs, i))
goto next_group;
if (i !=0 ) {
retval = io_channel_write_blk(fs->io, group_block,
-SUPERBLOCK_SIZE,
@ -108,6 +143,7 @@ errcode_t ext2fs_flush(ext2_filsys fs)
goto errout;
group_ptr += fs->blocksize;
}
next_group:
group_block += EXT2_BLOCKS_PER_GROUP(fs->super);
}

View File

@ -127,6 +127,28 @@ errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ino_t ino, blk_t blk,
return 0;
}
/*
* Change the directory block to the directory block list
*/
errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ino_t ino, blk_t blk,
int blockcnt)
{
struct ext2_db_entry *ent;
int i;
EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
for (i=0; i < dblist->count; i++) {
if ((dblist->list[i].ino != ino) ||
(dblist->list[i].blockcnt != blockcnt))
continue;
dblist->list[i].blk = blk;
dblist->sorted = 0;
return 0;
}
return ENOENT;
}
/*
* This function iterates over the directory block list
*/
@ -151,7 +173,6 @@ errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
if (ret & DBLIST_ABORT)
return 0;
}
return 0;
}

View File

@ -138,3 +138,7 @@
00000000 T _ext2fs_icount_decrement libext2fs icount
00000000 T _ext2fs_icount_store libext2fs icount
00000000 T _ext2fs_get_icount_size libext2fs icount
00000000 T _ext2fs_create_icount2 libext2fs icount
00000000 T _ext2fs_get_library_version libext2fs version
00000000 T _ext2fs_parse_version_string libext2fs version
00000000 T _ext2fs_set_dir_block libext2fs dblist

View File

@ -341,7 +341,19 @@ struct ext2fs_sb {
char s_last_mounted[64]; /* directory where last mounted */
__u32 s_reserved[206]; /* Padding to the end of the block */
};
/*
* Feature set definitions (that might not be in ext2_fs.h
* (was EXT2_COMPAT_SPARSE_SUPER)
*/
#ifndef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
#endif
#define EXT2_LIB_FEATURE_COMPAT_SUPP 0
#define EXT2_LIB_FEATURE_INCOMPAT_SUPP 0
#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
/*
* function prototypes
*/
@ -442,6 +454,7 @@ extern errcode_t ext2fs_check_desc(ext2_filsys fs);
/* closefs.c */
extern errcode_t ext2fs_close(ext2_filsys fs);
extern errcode_t ext2fs_flush(ext2_filsys fs);
extern int ext2fs_bg_has_super(ext2_filsys fs, int group_block);
/* cmp_bitmaps.c */
extern errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
@ -461,6 +474,8 @@ errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
struct ext2_db_entry *db_info,
void *private),
void *private);
errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ino_t ino, blk_t blk,
int blockcnt);
/* dblist_dir.c */
extern errcode_t
@ -544,6 +559,8 @@ extern errcode_t ext2fs_check_directory(ext2_filsys fs, ino_t ino);
/* icount.c */
extern void ext2fs_free_icount(ext2_icount_t icount);
extern errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, int size,
ext2_icount_t hint, ext2_icount_t *ret);
extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size,
ext2_icount_t *ret);
extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ino_t ino,
@ -555,6 +572,7 @@ extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ino_t ino,
extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ino_t ino,
__u16 count);
extern ino_t ext2fs_get_icount_size(ext2_icount_t icount);
errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *);
/* ismounted.c */
extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags);
@ -621,7 +639,12 @@ extern void ext2fs_swap_inode(ext2_filsys fs,struct ext2_inode *t,
struct ext2_inode *f, int hostorder);
/* valid_blk.c */
int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode);
extern int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode);
/* version.c */
extern int ext2fs_parse_version_string(const char *ver_string);
extern int ext2fs_get_library_version(const char **ver_string,
const char **date_string);
/* inline functions */
extern void ext2fs_mark_super_dirty(ext2_filsys fs);

View File

@ -71,13 +71,20 @@ void ext2fs_free_icount(ext2_icount_t icount)
free(icount);
}
errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size,
ext2_icount_t *ret)
errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, int size,
ext2_icount_t hint, ext2_icount_t *ret)
{
ext2_icount_t icount;
errcode_t retval;
size_t bytes;
int i;
if (hint) {
EXT2_CHECK_MAGIC(hint, EXT2_ET_MAGIC_ICOUNT);
if (hint->size > size)
size = hint->size;
}
icount = malloc(sizeof(struct ext2_icount));
if (!icount)
return ENOMEM;
@ -125,8 +132,18 @@ errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size,
icount->cursor = 0;
icount->num_inodes = fs->super->s_inodes_count;
*ret = icount;
/*
* Populate the sorted list with those entries which were
* found in the hint icount (since those are ones which will
* likely need to be in the sorted list this time around).
*/
if (hint) {
for (i=0; i < hint->count; i++)
icount->list[i].ino = hint->list[i].ino;
icount->count = hint->count;
}
*ret = icount;
return 0;
errout:
@ -134,65 +151,22 @@ errout:
return(retval);
}
/*
* get_icount_el() --- given an inode number, try to find icount
* information in the sorted list. We use a binary search...
*/
static struct ext2_icount_el *get_icount_el(ext2_icount_t icount, ino_t ino)
errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size,
ext2_icount_t *ret)
{
int low, high, mid;
if (!icount || !icount->list || !icount->count)
return 0;
if (icount->multiple &&
!ext2fs_test_inode_bitmap(icount->multiple, ino))
return 0;
low = 0;
high = icount->count-1;
if (ino == icount->list[low].ino) {
icount->cursor = low+1;
return &icount->list[low];
}
if (ino == icount->list[high].ino) {
icount->cursor = 0;
return &icount->list[high];
}
if (icount->cursor >= icount->count)
icount->cursor = 0;
if (ino == icount->list[icount->cursor].ino)
return &icount->list[icount->cursor++];
#if 0
printf("Non-cursor get_icount_el: %u\n", ino);
#endif
while (low < high) {
mid = (low+high)/2;
if (mid == low || mid == high)
break;
if (ino == icount->list[mid].ino) {
icount->cursor = mid;
return &icount->list[mid];
}
if (ino < icount->list[mid].ino)
high = mid;
else
low = mid;
}
return 0;
return ext2fs_create_icount2(fs, flags, size, 0, ret);
}
/*
* put_icount_el() --- given an inode number, create a new entry in
* the sorted list. This function is optimized for adding values
* in ascending order.
* insert_icount_el() --- Insert a new entry into the sorted list at a
* specified position.
*/
static struct ext2_icount_el *put_icount_el(ext2_icount_t icount, ino_t ino)
static struct ext2_icount_el *insert_icount_el(ext2_icount_t icount,
ino_t ino, int pos)
{
struct ext2_icount_el *el, *new_list;
ino_t new_size = 0;
int i, j;
int num;
if (icount->count >= icount->size) {
if (icount->count) {
@ -212,31 +186,112 @@ static struct ext2_icount_el *put_icount_el(ext2_icount_t icount, ino_t ino)
icount->size = new_size;
icount->list = new_list;
}
/*
* Normally, get_icount_el is called with each inode in
* sequential order; but once in a while (like when pass 3
* needs to recreate the root directory or lost+found
* directory) it is called out of order.
*/
if (icount->count && icount->list[icount->count-1].ino >= ino) {
for (i = icount->count-1; i > 0; i--)
if (icount->list[i-1].ino < ino)
break;
el = &icount->list[i];
if (el->ino != ino) {
for (j = icount->count++; j > i; j--)
icount->list[j] = icount->list[j-1];
el->count = 0;
}
} else {
el = &icount->list[icount->count++];
el->count = 0;
num = icount->count - pos;
if (num < 0)
return 0; /* should never happen */
if (num) {
memmove(&icount->list[pos+1], &icount->list[pos],
sizeof(struct ext2_icount_el) * num);
}
icount->count++;
el = &icount->list[pos];
el->count = 0;
el->ino = ino;
return el;
}
/*
* get_icount_el() --- given an inode number, try to find icount
* information in the sorted list. If the create flag is set,
* and we can't find an entry, create one in the sorted list.
*/
static struct ext2_icount_el *get_icount_el(ext2_icount_t icount,
ino_t ino, int create)
{
float range;
int low, high, mid;
ino_t lowval, highval;
if (!icount || !icount->list)
return 0;
if (create && ((icount->count == 0) ||
(ino > icount->list[icount->count-1].ino))) {
return insert_icount_el(icount, ino, icount->count);
}
if (icount->count == 0)
return 0;
if (icount->cursor >= icount->count)
icount->cursor = 0;
if (ino == icount->list[icount->cursor].ino)
return &icount->list[icount->cursor++];
#if 0
printf("Non-cursor get_icount_el: %u\n", ino);
#endif
low = 0;
high = icount->count-1;
while (low <= high) {
#if 0
mid = (low+high)/2;
#else
if (low == high)
mid = low;
else {
/* Interpolate for efficiency */
lowval = icount->list[low].ino;
highval = icount->list[high].ino;
if (ino < lowval)
range = 0;
else if (ino > highval)
range = 1;
else
range = ((float) (ino - lowval)) /
(highval - lowval);
mid = low + ((int) (range * (high-low)));
}
#endif
if (ino == icount->list[mid].ino) {
icount->cursor = mid+1;
return &icount->list[mid];
}
if (ino < icount->list[mid].ino)
high = mid-1;
else
low = mid+1;
}
/*
* If we need to create a new entry, it should be right at
* low (where high will be left at low-1).
*/
if (create)
return insert_icount_el(icount, ino, low);
return 0;
}
errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *out)
{
errcode_t ret = 0;
int i;
const char *bad = "bad icount";
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
if (icount->count > icount->size) {
fprintf(out, "%s: count > size\n", bad);
return EINVAL;
}
for (i=1; i < icount->count; i++) {
if (icount->list[i-1].ino >= icount->list[i].ino) {
fprintf(out, "%s: list[%d].ino=%u, list[%d].ino=%u\n",
bad, i-1, icount->list[i-1].ino,
i, icount->list[i].ino);
ret = EINVAL;
}
}
return ret;
}
errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ino_t ino, __u16 *ret)
{
@ -244,11 +299,19 @@ errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ino_t ino, __u16 *ret)
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
if (!ino || (ino > icount->num_inodes))
return EINVAL;
if (ext2fs_test_inode_bitmap(icount->single, ino)) {
*ret = 1;
return 0;
}
el = get_icount_el(icount, ino);
if (icount->multiple &&
!ext2fs_test_inode_bitmap(icount->multiple, ino)) {
*ret = 0;
return 0;
}
el = get_icount_el(icount, ino, 0);
if (!el) {
*ret = 0;
return 0;
@ -264,14 +327,19 @@ errcode_t ext2fs_icount_increment(ext2_icount_t icount, ino_t ino,
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
if (!ino || (ino > icount->num_inodes))
return EINVAL;
if (ext2fs_test_inode_bitmap(icount->single, ino)) {
/*
* If the existing count is 1, then we know there is
* no entry in the list, so use put_icount_el().
* no entry in the list.
*/
el = put_icount_el(icount, ino);
el = get_icount_el(icount, ino, 1);
if (!el)
return ENOMEM;
ext2fs_unmark_inode_bitmap(icount->single, ino);
el->count = 2;
} else if (icount->multiple) {
/*
* The count is either zero or greater than 1; if the
@ -280,13 +348,10 @@ errcode_t ext2fs_icount_increment(ext2_icount_t icount, ino_t ino,
* get_icount_el().
*/
if (ext2fs_test_inode_bitmap(icount->multiple, ino)) {
el = get_icount_el(icount, ino);
if (!el) {
/* should never happen */
el = put_icount_el(icount, ino);
if (!el)
return ENOMEM;
}
el = get_icount_el(icount, ino, 1);
if (!el)
return ENOMEM;
el->count++;
} else {
/*
* The count was zero; mark the single bitmap
@ -303,20 +368,16 @@ errcode_t ext2fs_icount_increment(ext2_icount_t icount, ino_t ino,
* The count is either zero or greater than 1; try to
* find an entry in the list to determine which.
*/
el = get_icount_el(icount, ino);
el = get_icount_el(icount, ino, 0);
if (!el) {
/* No entry means the count was zero */
goto zero_count;
}
el = put_icount_el(icount, ino);
el = get_icount_el(icount, ino, 1);
if (!el)
return ENOMEM;
}
if (ext2fs_test_inode_bitmap(icount->single, ino)) {
ext2fs_unmark_inode_bitmap(icount->single, ino);
el->count = 2;
} else
el->count++;
}
if (icount->multiple)
ext2fs_mark_inode_bitmap(icount->multiple, ino);
if (ret)
@ -329,6 +390,9 @@ errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ino_t ino,
{
struct ext2_icount_el *el;
if (!ino || (ino > icount->num_inodes))
return EINVAL;
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
if (ext2fs_test_inode_bitmap(icount->single, ino)) {
@ -336,7 +400,7 @@ errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ino_t ino,
if (icount->multiple)
ext2fs_unmark_inode_bitmap(icount->multiple, ino);
else {
el = get_icount_el(icount, ino);
el = get_icount_el(icount, ino, 0);
if (el)
el->count = 0;
}
@ -345,8 +409,12 @@ errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ino_t ino,
return 0;
}
el = get_icount_el(icount, ino);
if (!el)
if (icount->multiple &&
!ext2fs_test_inode_bitmap(icount->multiple, ino))
return EINVAL;
el = get_icount_el(icount, ino, 0);
if (!el || el->count == 0)
return EINVAL;
el->count--;
@ -365,6 +433,9 @@ errcode_t ext2fs_icount_store(ext2_icount_t icount, ino_t ino,
{
struct ext2_icount_el *el;
if (!ino || (ino > icount->num_inodes))
return EINVAL;
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
if (count == 1) {
@ -382,7 +453,7 @@ errcode_t ext2fs_icount_store(ext2_icount_t icount, ino_t ino,
*/
ext2fs_unmark_inode_bitmap(icount->multiple, ino);
} else {
el = get_icount_el(icount, ino);
el = get_icount_el(icount, ino, 0);
if (el)
el->count = 0;
}
@ -392,7 +463,7 @@ errcode_t ext2fs_icount_store(ext2_icount_t icount, ino_t ino,
/*
* Get the icount element
*/
el = put_icount_el(icount, ino);
el = get_icount_el(icount, ino, 1);
if (!el)
return ENOMEM;
el->count = count;

View File

@ -58,6 +58,7 @@ errcode_t ext2fs_initialize(const char *name, int flags,
ext2_filsys fs;
errcode_t retval;
struct ext2_super_block *super;
struct ext2fs_sb *s;
int frags_per_block;
int rem;
int overhead = 0;
@ -91,9 +92,12 @@ errcode_t ext2fs_initialize(const char *name, int flags,
goto cleanup;
}
memset(super, 0, SUPERBLOCK_SIZE);
s = (struct ext2fs_sb *) super;
#define set_field(field, default) (super->field = param->field ? \
param->field : (default))
#define set_ext2_field(field, default) (s->field = param->field ? \
param->field : (default))
super->s_magic = EXT2_SUPER_MAGIC;
super->s_state = EXT2_VALID_FS;
@ -103,7 +107,13 @@ errcode_t ext2fs_initialize(const char *name, int flags,
set_field(s_first_data_block, super->s_log_block_size ? 0 : 1);
set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT);
set_field(s_errors, EXT2_ERRORS_DEFAULT);
set_ext2_field(s_feature_compat, 0);
set_ext2_field(s_feature_incompat, 0);
set_ext2_field(s_feature_ro_compat, 0);
if (s->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)
return EXT2_ET_UNSUPP_FEATURE;
if (s->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)
return EXT2_ET_RO_UNSUPP_FEATURE;
#ifdef EXT2_DYNAMIC_REV
set_field(s_rev_level, EXT2_GOOD_OLD_REV);
@ -122,7 +132,8 @@ errcode_t ext2fs_initialize(const char *name, int flags,
fs->fragsize = EXT2_FRAG_SIZE(super);
frags_per_block = fs->blocksize / fs->fragsize;
set_field(s_blocks_per_group, 8192); /* default: 8192 blocks/group */
/* default: (fs->blocksize*8) blocks/group */
set_field(s_blocks_per_group, fs->blocksize*8);
super->s_frags_per_group = super->s_blocks_per_group * frags_per_block;
super->s_blocks_count = param->s_blocks_count;
@ -187,16 +198,6 @@ retry:
fs->group_desc_count;
super->s_free_inodes_count = super->s_inodes_count;
/*
* Overhead is the number of bookkeeping blocks per group. It
* includes the superblock backup, the group descriptor
* backups, the inode bitmap, the block bitmap, and the inode
* table.
*/
overhead = 3 + fs->desc_blocks + fs->inode_blocks_per_group;
super->s_free_blocks_count = super->s_blocks_count -
super->s_first_data_block - (overhead*fs->group_desc_count);
/*
* See if the last group is big enough to support the
* necessary data structures. If not, we need to get rid of
@ -250,11 +251,8 @@ retry:
* by this routine), they are accounted for nevertheless.
*/
group_block = super->s_first_data_block;
super->s_free_blocks_count = 0;
for (i = 0; i < fs->group_desc_count; i++) {
for (j=0; j < fs->desc_blocks+1; j++)
ext2fs_mark_block_bitmap(fs->block_map,
group_block + j);
if (i == fs->group_desc_count-1) {
numblocks = (fs->super->s_blocks_count -
fs->super->s_first_data_block) %
@ -263,8 +261,17 @@ retry:
numblocks = fs->super->s_blocks_per_group;
} else
numblocks = fs->super->s_blocks_per_group;
numblocks -= 3 + fs->desc_blocks + fs->inode_blocks_per_group;
if (ext2fs_bg_has_super(fs, i)) {
for (j=0; j < fs->desc_blocks+1; j++)
ext2fs_mark_block_bitmap(fs->block_map,
group_block + j);
numblocks -= 1 + fs->desc_blocks;
}
numblocks -= 2 + fs->inode_blocks_per_group;
super->s_free_blocks_count += numblocks;
fs->group_desc[i].bg_free_blocks_count = numblocks;
fs->group_desc[i].bg_free_inodes_count =
fs->super->s_inodes_per_group;

View File

@ -51,6 +51,7 @@ errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
{
ext2_inode_scan scan;
errcode_t retval;
errcode_t (*save_get_blocks)(ext2_filsys fs, ino_t ino, blk_t *blocks);
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
@ -59,11 +60,18 @@ errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
* scanning functions require it.
*/
if (fs->badblocks == 0) {
/*
* Temporarly save fs->get_blocks and set it to zero,
* for compatibility with old e2fsck's.
*/
save_get_blocks = fs->get_blocks;
fs->get_blocks = 0;
retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
if (retval && fs->badblocks) {
badblocks_list_free(fs->badblocks);
fs->badblocks = 0;
}
fs->get_blocks = save_get_blocks;
}
scan = (ext2_inode_scan) malloc(sizeof(struct ext2_struct_inode_scan));

View File

@ -126,12 +126,13 @@ errcode_t ext2fs_open(const char *name, int flags, int superblock,
*/
if (!(flags & EXT2_FLAG_FORCE)) {
s = (struct ext2fs_sb *) fs->super;
if (s->s_feature_incompat) {
if (s->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) {
retval = EXT2_ET_UNSUPP_FEATURE;
goto cleanup;
}
if ((flags & EXT2_FLAG_RW) &&
s->s_feature_ro_compat) {
(s->s_feature_ro_compat &
~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)) {
retval = EXT2_ET_RO_UNSUPP_FEATURE;
goto cleanup;
}

53
lib/ext2fs/version.c Normal file
View File

@ -0,0 +1,53 @@
/*
* version.c --- Return the version of the ext2 library
*
* Copyright (C) 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <et/com_err.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include <linux/ext2_fs.h>
#include "ext2fs.h"
#include "../../version.h"
static const char *lib_version = E2FSPROGS_VERSION;
static const char *lib_date = E2FSPROGS_DATE;
int ext2fs_parse_version_string(const char *ver_string)
{
const char *cp;
int version = 0;
for (cp = lib_version; *cp; cp++) {
if (!isdigit(*cp))
continue;
version = (version * 10) + (*cp - '0');
}
return version;
}
int ext2fs_get_library_version(const char **ver_string,
const char **date_string)
{
if (ver_string)
*ver_string = lib_version;
if (date_string)
*date_string = lib_date;
return ext2fs_parse_version_string(lib_version);
}

View File

@ -9,8 +9,8 @@
* $Locker$
*
* $Log$
* Revision 1.10 1997/04/29 16:15:48 tytso
* Checked in e2fsprogs-1.07
* Revision 1.11 1997/04/29 17:47:28 tytso
* Checked in e2fsprogs 1.08.
*
* Revision 1.1 1993/06/03 12:31:25 tytso
* Initial revision

View File

@ -1,3 +1,21 @@
Thu Apr 10 07:08:03 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* dumpe2fs.c (list_desc): List the offsets of the inode and block
bitmaps, and the inode table. List the block boundaries
for the groups.
Sat Apr 5 11:55:52 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* tune2fs.c (main): Implement the -s flag allows the user to
set and reset the sparse superblock flag.
* mke2fs.c (PRS): By default generate DYNAMIC revision
filesystems. The -s flag controls whether or not the
sparse superblock flag is set.
(PRS): Change to allow the user to specify the true
maximum number of blocks per group to reflect the
blocksize.
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
* Release of E2fsprogs version 1.07

View File

@ -77,18 +77,27 @@ static void print_free (unsigned long group, char * bitmap,
static void list_desc (ext2_filsys fs)
{
unsigned long i;
blk_t group_blk, next_blk;
char * block_bitmap = fs->block_map->bitmap;
char * inode_bitmap = fs->inode_map->bitmap;
printf ("\n");
for (i = 0; i < fs->group_desc_count; i++)
{
printf ("Group %lu:\n", i);
printf (" Block bitmap at %u, Inode bitmap at %u, "
"Inode table at %u\n",
group_blk = fs->super->s_first_data_block;
for (i = 0; i < fs->group_desc_count; i++) {
next_blk = group_blk + fs->super->s_blocks_per_group;
if (next_blk > fs->super->s_blocks_count)
next_blk = fs->super->s_blocks_count;
printf ("Group %lu: (Blocks %u -- %u)\n", i,
group_blk, next_blk -1 );
printf (" Block bitmap at %u (+%d), "
"Inode bitmap at %u (+%d)\n "
"Inode table at %u (+%d)\n",
fs->group_desc[i].bg_block_bitmap,
fs->group_desc[i].bg_block_bitmap - group_blk,
fs->group_desc[i].bg_inode_bitmap,
fs->group_desc[i].bg_inode_table);
fs->group_desc[i].bg_inode_bitmap - group_blk,
fs->group_desc[i].bg_inode_table,
fs->group_desc[i].bg_inode_table - group_blk);
printf (" %d free blocks, %d free inodes, %d directories\n",
fs->group_desc[i].bg_free_blocks_count,
fs->group_desc[i].bg_free_inodes_count,
@ -102,6 +111,7 @@ static void list_desc (ext2_filsys fs)
print_free (i, inode_bitmap, fs->super->s_inodes_per_group, 1);
inode_bitmap += fs->super->s_inodes_per_group / 8;
printf ("\n");
group_blk = next_blk;
}
}

View File

@ -40,6 +40,9 @@ mke2fs \- create a Linux second extended file system
.B \-q
]
[
.B -s sparse-super-flag
]
[
.B \-v
]
[
@ -114,6 +117,11 @@ of the mke2fs executable.
.I -q
Quiet execution. Useful if mke2fs is run in a script.
.TP
.I -s sparse-super-flag
If sparse-super-flag is 1, then turn on the sparse superblock flag.
If 0, then turn off the sparse superblock flag. (Currently, the sparse
superblock flag defaults to off.)
.TP
.I -v
Verbose execution.
.TP

View File

@ -486,6 +486,8 @@ static void show_stats(ext2_filsys fs)
col_left = 0;
for (i = 1; i < fs->group_desc_count; i++) {
group_block += s->s_blocks_per_group;
if (!ext2fs_bg_has_super(fs, i))
continue;
if (!col_left--) {
printf("\n\t");
col_left = 8;
@ -539,11 +541,14 @@ static void PRS(int argc, char *argv[])
char c;
int size;
char * tmp;
blk_t max = 8192;
int inode_ratio = 4096;
int reserved_ratio = 5;
errcode_t retval;
int sparse_option = -1;
char *oldpath = getenv("PATH");
struct ext2fs_sb *param_ext2 = (struct ext2fs_sb *) &param;
/* Update our PATH to include /sbin */
if (oldpath) {
char *newpath;
@ -560,6 +565,9 @@ static void PRS(int argc, char *argv[])
setbuf(stderr, NULL);
initialize_ext2_error_table();
memset(&param, 0, sizeof(struct ext2_super_block));
#ifdef EXT2_DYNAMIC_REV
param.s_rev_level = EXT2_DYNAMIC_REV;
#endif
fprintf (stderr, "mke2fs %s, %s for EXT2 FS %s, %s\n",
E2FSPROGS_VERSION, E2FSPROGS_DATE,
@ -567,7 +575,7 @@ static void PRS(int argc, char *argv[])
if (argc && *argv)
program_name = *argv;
while ((c = getopt (argc, argv,
"b:cf:g:i:l:m:o:qr:tvI:SFL:M:")) != EOF)
"b:cf:g:i:l:m:o:qr:s:tvI:SFL:M:")) != EOF)
switch (c) {
case 'b':
size = strtoul(optarg, &tmp, 0);
@ -578,6 +586,7 @@ static void PRS(int argc, char *argv[])
}
param.s_log_block_size =
log2(size >> EXT2_MIN_BLOCK_LOG_SIZE);
max = size * 8;
break;
case 'c':
case 't': /* Check for bad blocks */
@ -602,12 +611,6 @@ static void PRS(int argc, char *argv[])
"Illegal number for blocks per group");
exit(1);
}
if (param.s_blocks_per_group < 256 ||
param.s_blocks_per_group > 8192 || *tmp) {
com_err(program_name, 0,
"blocks per group count out of range");
exit(1);
}
if ((param.s_blocks_per_group % 8) != 0) {
com_err(program_name, 0,
"blocks per group must be multiple of 8");
@ -647,6 +650,9 @@ static void PRS(int argc, char *argv[])
case 'r':
param.s_rev_level = atoi(optarg);
break;
case 's':
sparse_option = atoi(optarg);
break;
#ifdef EXT2_DYNAMIC_REV
case 'I':
param.s_inode_size = atoi(optarg);
@ -705,6 +711,15 @@ static void PRS(int argc, char *argv[])
}
}
if (param.s_blocks_per_group) {
if (param.s_blocks_per_group < 256 ||
param.s_blocks_per_group > max || *tmp) {
com_err(program_name, 0,
"blocks per group count out of range");
exit(1);
}
}
/*
* Calculate number of inodes based on the inode ratio
*/
@ -716,6 +731,20 @@ static void PRS(int argc, char *argv[])
* Calculate number of blocks to reserve
*/
param.s_r_blocks_count = (param.s_blocks_count * reserved_ratio) / 100;
/*
* If we are using revision #1, use the sparse super feature
* by default
*/
#ifdef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
if ((sparse_option == 1)
#ifdef EXT2_DYNAMIC_REV
|| (param.s_rev_level >= EXT2_DYNAMIC_REV) && (!sparse_option)
#endif
)
param_ext2->s_feature_ro_compat |=
EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
#endif
}
int main (int argc, char *argv[])

View File

@ -31,6 +31,9 @@ tune2fs \- adjust tunable filesystem parameters on second extended filesystems
.I reserved-blocks-count
]
[
.B -s sparse-super-flag
]
[
.B -u
.I user
]
@ -97,6 +100,10 @@ adjust the reserved blocks percentage on the given device.
.I -r reserved-blocks-count
adjust the reserved blocks count on the given device.
.TP
.I -s sparse_super_flag
sets and resets the sparse_superblock flag. The sparse_superblock feature
saves space on really big filesystems.
.TP
.I -u user
set the user who can benefit from the reserved blocks.
.I user

View File

@ -63,6 +63,7 @@ int L_flag = 0;
int m_flag = 0;
int M_flag = 0;
int r_flag = 0;
int s_flag = -1;
int u_flag = 0;
int U_flag = 0;
int max_mount_count, mount_count;
@ -93,7 +94,7 @@ static volatile void usage (void)
{
fprintf (stderr, "Usage: %s [-c max-mounts-count] [-e errors-behavior] "
"[-g group]\n"
"\t[-i interval[d|m|w]] [-l] [-m reserved-blocks-percent]\n"
"\t[-i interval[d|m|w]] [-l] [-s] [-m reserved-blocks-percent]\n"
"\t[-r reserved-blocks-count] [-u user] [-C mount-count]\n"
"\t[-L volume-label] [-M last-mounted-dir] [-U UUID] "
"device\n", program_name);
@ -117,7 +118,7 @@ void main (int argc, char ** argv)
if (argc && *argv)
program_name = *argv;
initialize_ext2_error_table();
while ((c = getopt (argc, argv, "c:e:g:i:lm:r:u:C:L:M:U:")) != EOF)
while ((c = getopt (argc, argv, "c:e:g:i:lm:r:s:u:C:L:M:U:")) != EOF)
switch (c)
{
case 'c':
@ -253,6 +254,10 @@ void main (int argc, char ** argv)
r_flag = 1;
open_flag = EXT2_FLAG_RW;
break;
case 's':
s_flag = atoi(optarg);
open_flag = EXT2_FLAG_RW;
break;
case 'u':
resuid = strtoul (optarg, &tmp, 0);
if (*tmp)
@ -355,6 +360,48 @@ void main (int argc, char ** argv)
printf ("Setting reserved blocks count to %lu\n",
reserved_blocks);
}
if (s_flag == 1) {
#ifdef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
if (sb->s_feature_ro_compat &
EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)
fprintf(stderr, "\nThe filesystem already "
" has spare superblocks.\n");
else {
sb->s_feature_ro_compat |=
EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
fs->super->s_state &= ~EXT2_VALID_FS;
ext2fs_mark_super_dirty(fs);
printf("\nSparse superblock flag set. "
"Please run e2fsck on the filesystem.\n");
}
#else /* !EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER */
com_err (program_name, 0,
"The -s option is not supported by this version -- "
"Recompile with a newer kernel");
#endif /* EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER */
}
if (s_flag == 0) {
#ifdef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
if (!(sb->s_feature_ro_compat &
EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
fprintf(stderr, "\nThe filesystem already "
" does not support spare superblocks.\n");
else {
sb->s_feature_ro_compat &=
~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
fs->super->s_state &= ~EXT2_VALID_FS;
fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
ext2fs_mark_super_dirty(fs);
printf("\nSparse superblock flag cleared. "
"Please run e2fsck on the filesystem.\n");
}
#else /* !EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER */
com_err (program_name, 0,
"The -s option is not supported by this version -- "
"Recompile with a newer kernel");
#endif /* EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER */
}
if (u_flag)
#ifdef EXT2_DEF_RESUID
{

View File

@ -1,3 +1,16 @@
Wed Mar 26 09:29:25 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* e_icount_normal, e_icount_opt: New tests which validate the
icount abstraction.
* test_script.in: New feature; an argument of a single character
means do all the tests in that series.
Tue Mar 18 15:11:04 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* test_config (LANG): Set the language to be C so that the brel
and irel tests don't fail.
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
* Release of E2fsprogs version 1.07

View File

@ -8,18 +8,28 @@ if [ -f $test_dir/setup ]; then
fi
if [ "$class"x = x ]; then
class=`echo $test_name | sed -e 's/r_\([^_]*\)_\(.*\)/\1/'`
instance=`echo $test_name | sed -e 's/r_\([^_]*\)_\(.*\)/\2/'`
class=`echo $test_name | sed -e 's/e_\([^_]*\)_\(.*\)/\1/'`
instance=`echo $test_name | sed -e 's/e_\([^_]*\)_\(.*\)/\2/'`
fi
if [ "$OUT"x = x ]; then
OUT=$test_name.log
fi
if [ "$EXPECT"x = x ]; then
EXPECT=$SRCDIR/progs/rel_test/expect.$class
EXPECT=$SRCDIR/progs/test_data/expect.$class
fi
cat $SRCDIR/progs/rel_test/$instance.setup $SRCDIR/progs/rel_test/test.$class \
| $TEST_REL -f - > $OUT 2>&1
if [ "$class" = irel ]; then
TEST_PROG=$TEST_REL
elif [ "$class" = brel ]; then
TEST_PROG=$TEST_REL
elif [ "$class" = icount ]; then
TEST_PROG=$TEST_ICOUNT
else
TEST_PROG=/bin/cat
fi
cat $SRCDIR/progs/test_data/$instance.setup $SRCDIR/progs/test_data/test.$class \
| $TEST_PROG -f - > $OUT 2>&1
cmp -s $EXPECT $OUT
status=$?

View File

@ -0,0 +1 @@
inode counting abstraction optimized for storing inode counts

1
tests/e_icount_opt/name Normal file
View File

@ -0,0 +1 @@
inode counting abstraction optimized for counting

View File

@ -1,21 +1,28 @@
Filesystem did not have a UUID; generating one.
Pass 1: Checking inodes, blocks, and sizes
Inode 12 has illegal block(s). Clear? yes
Duplicate blocks found... invoking duplicate block passes.
Pass 1B: Rescan for duplicate/bad blocks
Duplicate/bad block(s) in inode 12: 3 4 6
Pass 1C: Scan directories for inodes with dup blocks.
Pass 1D: Reconciling duplicate blocks
(There are 1 inodes containing duplicate/bad blocks.)
Block #1 (3) overlaps filesystem metadata in inode 12. CLEARED.
Block #2 (4) overlaps filesystem metadata in inode 12. CLEARED.
Block #3 (6) overlaps filesystem metadata in inode 12. CLEARED.
Inode 12, i_size is 4096, should be 1024. Fix? yes
File /foo (inode #12, mod time Thu Apr 28 17:57:53 1994)
has 3 duplicate block(s), shared with 1 file(s):
<filesystem metadata>
Clone duplicate/bad blocks? yes
Inode 12, i_blocks is 8, should be 2. Fix? yes
Pass 2: Checking directory structure
Directory inode 12 has an unallocated block #1. Allocate? yes
Directory inode 12, block 1, offset 0: directory corrupted
Salvage? yes
Directory inode 12 has an unallocated block #2. Allocate? yes
Directory inode 12, block 2, offset 0: directory corrupted
Salvage? yes
Directory inode 12 has an unallocated block #3. Allocate? yes
Directory inode 12, block 3, offset 0: directory corrupted
Salvage? yes
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts

View File

@ -1,12 +1,18 @@
Filesystem did not have a UUID; generating one.
Pass 1: Checking inodes, blocks, and sizes
Inode 12 has illegal block(s). Clear? yes
Duplicate blocks found... invoking duplicate block passes.
Pass 1B: Rescan for duplicate/bad blocks
Duplicate/bad block(s) in inode 12: 2 3 1
Pass 1C: Scan directories for inodes with dup blocks.
Pass 1D: Reconciling duplicate blocks
(There are 1 inodes containing duplicate/bad blocks.)
File /termcap (inode #12, mod time Sun Jan 2 08:29:13 1994)
has 3 duplicate block(s), shared with 1 file(s):
<filesystem metadata>
Clone duplicate/bad blocks? yes
Block #4 (2) overlaps filesystem metadata in inode 12. CLEARED.
Block #5 (3) overlaps filesystem metadata in inode 12. CLEARED.
Block #6 (1) overlaps filesystem metadata in inode 12. CLEARED.
Inode 12, i_blocks is 34, should be 28. Fix? yes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
@ -15,9 +21,7 @@ Pass 5: Checking group summary information
Fix summary information? yes
Block bitmap differences: -29 -30 -31. FIXED
Free blocks count wrong for group 0 (61, counted=64). FIXED
Free blocks count wrong (61, counted=64). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 12/32 files (8.3% non-contiguous), 36/100 blocks
test_filesys: 12/32 files (8.3% non-contiguous), 39/100 blocks
Exit status is 1

View File

@ -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: 12/32 files (8.3% non-contiguous), 36/100 blocks
test_filesys: 12/32 files (8.3% non-contiguous), 39/100 blocks
Exit status is 0

View File

@ -1,9 +1,9 @@
Note: if there is several inode or block bitmap blocks
which require relocation, or one part of the inode table
which must be moved, you may wish to try running e2fsck
the '-b 8193' option first. The problem may lie only with
the primary block group descriptor, and the backup block
group descriptor may be OK.
with the '-b 8193' option first. The problem may lie only
with the primary block group descriptor, and the backup
block group descriptor may be OK.
Block bitmap for group 0 is not in group. (block 4096)
Relocate? yes

View File

@ -1,9 +1,9 @@
Note: if there is several inode or block bitmap blocks
which require relocation, or one part of the inode table
which must be moved, you may wish to try running e2fsck
the '-b 8193' option first. The problem may lie only with
the primary block group descriptor, and the backup block
group descriptor may be OK.
with the '-b 8193' option first. The problem may lie only
with the primary block group descriptor, and the backup
block group descriptor may be OK.
Inode bitmap for group 0 is not in group. (block 4000)
Relocate? yes

View File

@ -1,9 +1,9 @@
Note: if there is several inode or block bitmap blocks
which require relocation, or one part of the inode table
which must be moved, you may wish to try running e2fsck
the '-b 8193' option first. The problem may lie only with
the primary block group descriptor, and the backup block
group descriptor may be OK.
with the '-b 8193' option first. The problem may lie only
with the primary block group descriptor, and the backup
block group descriptor may be OK.
Inode table for group 0 is not in group. (block 40000)
WARNING: SEVERE DATA LOSS POSSIBLE.

View File

@ -1,8 +1,8 @@
which require relocation, or one part of the inode table
which must be moved, you may wish to try running e2fsck
the '-b 8193' option first. The problem may lie only with
the primary block group descriptor, and the backup block
group descriptor may be OK.
with the '-b 8193' option first. The problem may lie only
with the primary block group descriptor, and the backup
block group descriptor may be OK.
test_filesys: Block bitmap for group 0 is not in group. (block 0)

4
tests/progs/ChangeLog Normal file
View File

@ -0,0 +1,4 @@
Wed Mar 26 15:38:52 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* test_icount.c: New file which tests the icount abstraction.

View File

@ -13,10 +13,12 @@ INSTALL = @INSTALL@
MK_CMDS= ../../lib/ss/mk_cmds
PROGS= test_rel
PROGS= test_rel test_icount
TEST_REL_OBJS= test_rel.o test_rel_cmds.o
TEST_ICOUNT_OBJS= test_icount.o test_icount_cmds.o
SRCS= $(srcdir)/test_rel.c
LIBS= $(LIBEXT2FS) $(LIBSS) $(LIBCOM_ERR)
@ -27,14 +29,21 @@ DEPLIBS= $(LIBEXT2FS) $(LIBSS) $(LIBCOM_ERR)
all:: $(PROGS)
test_rel: $(TEST_REL_OBJS)
test_rel: $(TEST_REL_OBJS) $(DEPLIBS)
$(LD) $(ALL_LDFLAGS) -o test_rel $(TEST_REL_OBJS) $(LIBS)
test_rel_cmds.c: test_rel_cmds.ct
$(MK_CMDS) $(srcdir)/test_rel_cmds.ct
test_icount: $(TEST_ICOUNT_OBJS) $(DEPLIBS)
$(LD) $(ALL_LDFLAGS) -o test_icount $(TEST_ICOUNT_OBJS) $(LIBS)
test_icount_cmds.c: test_icount_cmds.ct
$(MK_CMDS) $(srcdir)/test_icount_cmds.ct
clean:
$(RM) -f $(PROGS) test_rel_cmds.c \#* *.s *.o *.a *~ core
$(RM) -f $(PROGS) test_rel_cmds.c test_icount_cmds.c \
\#* *.s *.o *.a *~ core
install:

View File

@ -0,0 +1,191 @@
test_icount: validate
Icount structure successfully validated
test_icount: store 0
usage: store inode counttest_icount: fetch 0
fetch: Invalid argument while calling ext2fs_icount_fetch
test_icount: increment 0
increment: Invalid argument while calling ext2fs_icount_increment
test_icount: decrement 0
decrement: Invalid argument while calling ext2fs_icount_increment
test_icount: store 20001
usage: store inode counttest_icount: fetch 20001
fetch: Invalid argument while calling ext2fs_icount_fetch
test_icount: increment 20001
increment: Invalid argument while calling ext2fs_icount_increment
test_icount: decrement 20001
decrement: Invalid argument while calling ext2fs_icount_increment
test_icount: validate
Icount structure successfully validated
test_icount: fetch 1
Count is 0
test_icount: store 1 1
test_icount: fetch 1
Count is 1
test_icount: store 1 2
test_icount: fetch 1
Count is 2
test_icount: store 1 3
test_icount: fetch 1
Count is 3
test_icount: store 1 1
test_icount: fetch 1
Count is 1
test_icount: store 1 0
test_icount: fetch 1
Count is 0
test_icount: fetch 20000
Count is 0
test_icount: store 20000 0
test_icount: fetch 20000
Count is 0
test_icount: store 20000 3
test_icount: fetch 20000
Count is 3
test_icount: store 20000 0
test_icount: fetch 20000
Count is 0
test_icount: store 20000 42
test_icount: fetch 20000
Count is 42
test_icount: store 20000 1
test_icount: fetch 20000
Count is 1
test_icount: store 20000 0
test_icount: fetch 20000
Count is 0
test_icount: get_size
Size of icount is: 5
test_icount: decrement 2
decrement: Invalid argument while calling ext2fs_icount_increment
test_icount: increment 2
Count is now 1
test_icount: fetch 2
Count is 1
test_icount: increment 2
Count is now 2
test_icount: fetch 2
Count is 2
test_icount: increment 2
Count is now 3
test_icount: fetch 2
Count is 3
test_icount: increment 2
Count is now 4
test_icount: fetch 2
Count is 4
test_icount: decrement 2
Count is now 3
test_icount: fetch 2
Count is 3
test_icount: decrement 2
Count is now 2
test_icount: fetch 2
Count is 2
test_icount: decrement 2
Count is now 1
test_icount: fetch 2
Count is 1
test_icount: decrement 2
Count is now 0
test_icount: decrement 2
decrement: Invalid argument while calling ext2fs_icount_increment
test_icount: store 3 1
test_icount: increment 3
Count is now 2
test_icount: fetch 3
Count is 2
test_icount: decrement 3
Count is now 1
test_icount: fetch 3
Count is 1
test_icount: decrement 3
Count is now 0
test_icount: store 4 0
test_icount: fetch 4
Count is 0
test_icount: increment 4
Count is now 1
test_icount: increment 4
Count is now 2
test_icount: fetch 4
Count is 2
test_icount: decrement 4
Count is now 1
test_icount: decrement 4
Count is now 0
test_icount: store 4 42
test_icount: store 4 0
test_icount: increment 4
Count is now 1
test_icount: increment 4
Count is now 2
test_icount: increment 4
Count is now 3
test_icount: decrement 4
Count is now 2
test_icount: decrement 4
Count is now 1
test_icount: decrement 4
Count is now 0
test_icount: decrement 4
decrement: Invalid argument while calling ext2fs_icount_increment
test_icount: decrement 4
decrement: Invalid argument while calling ext2fs_icount_increment
test_icount: store 5 4
test_icount: decrement 5
Count is now 3
test_icount: decrement 5
Count is now 2
test_icount: decrement 5
Count is now 1
test_icount: decrement 5
Count is now 0
test_icount: decrement 5
decrement: Invalid argument while calling ext2fs_icount_increment
test_icount: get_size
Size of icount is: 105
test_icount: validate
Icount structure successfully validated
test_icount: store 10 10
test_icount: store 20 20
test_icount: store 30 30
test_icount: store 40 40
test_icount: store 50 50
test_icount: store 60 60
test_icount: store 70 70
test_icount: store 80 80
test_icount: store 90 90
test_icount: store 100 100
test_icount: store 15 15
test_icount: store 25 25
test_icount: store 35 35
test_icount: store 45 45
test_icount: store 55 55
test_icount: store 65 65
test_icount: store 75 75
test_icount: store 85 85
test_icount: store 95 95
test_icount: dump
10: 10
15: 15
20: 20
25: 25
30: 30
35: 35
40: 40
45: 45
50: 50
55: 55
60: 60
65: 65
70: 70
75: 75
80: 80
85: 85
90: 90
95: 95
100: 100
test_icount: get_size
Size of icount is: 105
test_icount: validate
Icount structure successfully validated

View File

@ -0,0 +1 @@
-create

View File

@ -0,0 +1 @@
-create -i

View File

@ -0,0 +1,136 @@
#
# This is the test script for the icount abstraction
#
# Copyright 1997 by Theodore Ts'o. This file may be redistributed
# under the terms of the GNU Public License.
#
#
# First let's test the boundary cases for illegal arguments
#
validate
store 0
fetch 0
increment 0
decrement 0
store 20001
fetch 20001
increment 20001
decrement 20001
validate
#
# OK, now let's test fetch and store. We also test the boundary cases
# for legal inodes here.
#
fetch 1
store 1 1
fetch 1
store 1 2
fetch 1
store 1 3
fetch 1
store 1 1
fetch 1
store 1 0
fetch 1
fetch 20000
store 20000 0
fetch 20000
store 20000 3
fetch 20000
store 20000 0
fetch 20000
store 20000 42
fetch 20000
store 20000 1
fetch 20000
store 20000 0
fetch 20000
get_size
#
# Time to test increment. First increment from 0 (previously unreferenced)
#
decrement 2
increment 2
fetch 2
increment 2
fetch 2
increment 2
fetch 2
increment 2
fetch 2
decrement 2
fetch 2
decrement 2
fetch 2
decrement 2
fetch 2
decrement 2
decrement 2
#
# Store 1 then test...
#
store 3 1
increment 3
fetch 3
decrement 3
fetch 3
decrement 3
#
# Store 0 then test
#
store 4 0
fetch 4
increment 4
increment 4
fetch 4
decrement 4
decrement 4
#
# Store something, then store 0, then test...
#
store 4 42
store 4 0
increment 4
increment 4
increment 4
decrement 4
decrement 4
decrement 4
decrement 4
decrement 4
#
# store something, then decrement to zero
#
store 5 4
decrement 5
decrement 5
decrement 5
decrement 5
decrement 5
#
# Test insert
#
get_size
validate
store 10 10
store 20 20
store 30 30
store 40 40
store 50 50
store 60 60
store 70 70
store 80 80
store 90 90
store 100 100
store 15 15
store 25 25
store 35 35
store 45 45
store 55 55
store 65 65
store 75 75
store 85 85
store 95 95
dump
get_size
validate

361
tests/progs/test_icount.c Normal file
View File

@ -0,0 +1,361 @@
/*
* test_icount.c
*
* Copyright (C) 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
#include <fcntl.h>
#include <linux/ext2_fs.h>
#include <et/com_err.h>
#include <ss/ss.h>
#include <ext2fs/ext2fs.h>
#include <ext2fs/irel.h>
#include <ext2fs/brel.h>
extern ss_request_table test_cmds;
#include "test_icount.h"
ext2_filsys test_fs;
ext2_icount_t test_icount;
/*
* Helper function which assures that the icount structure is valid
*/
static int check_icount(char *request)
{
if (test_icount)
return 0;
com_err(request, 0, "The icount structure must be allocated.");
return 1;
}
/*
* Helper function which parses an inode number.
*/
static int parse_inode(const char *request, const char *desc,
const char *str, ino_t *ino)
{
char *tmp;
*ino = strtoul(str, &tmp, 0);
if (*tmp) {
com_err(request, 0, "Bad %s - %s", desc, str);
return 1;
}
return 0;
}
void do_create_icount(int argc, char **argv)
{
errcode_t retval;
char *progname;
int flags = 0;
ino_t size = 5;
progname = *argv;
argv++; argc --;
if (argc && !strcmp("-i", *argv)) {
flags |= EXT2_ICOUNT_OPT_INCREMENT;
argv++; argc--;
}
if (argc) {
if (parse_inode(progname, "icount size", argv[0], &size))
return;
argv++; argc--;
}
#if 0
printf("Creating icount... flags=%d, size=%d\n", flags, (int) size);
#endif
retval = ext2fs_create_icount(test_fs, flags, (int) size,
&test_icount);
if (retval) {
com_err(progname, retval, "while creating icount");
return;
}
}
void do_free_icount(int argc, char **argv)
{
if (check_icount(argv[0]))
return;
ext2fs_free_icount(test_icount);
test_icount = 0;
}
void do_fetch(int argc, char **argv)
{
const char *usage = "usage: %s inode";
errcode_t retval;
ino_t ino;
__u16 count;
if (argc < 2) {
printf(usage, argv[0]);
return;
}
if (check_icount(argv[0]))
return;
if (parse_inode(argv[0], "inode", argv[1], &ino))
return;
retval = ext2fs_icount_fetch(test_icount, ino, &count);
if (retval) {
com_err(argv[0], retval, "while calling ext2fs_icount_fetch");
return;
}
printf("Count is %u\n", count);
}
void do_increment(int argc, char **argv)
{
const char *usage = "usage: %s inode";
errcode_t retval;
ino_t ino;
__u16 count;
if (argc < 2) {
printf(usage, argv[0]);
return;
}
if (check_icount(argv[0]))
return;
if (parse_inode(argv[0], "inode", argv[1], &ino))
return;
retval = ext2fs_icount_increment(test_icount, ino, &count);
if (retval) {
com_err(argv[0], retval,
"while calling ext2fs_icount_increment");
return;
}
printf("Count is now %u\n", count);
}
void do_decrement(int argc, char **argv)
{
const char *usage = "usage: %s inode";
errcode_t retval;
ino_t ino;
__u16 count;
if (argc < 2) {
printf(usage, argv[0]);
return;
}
if (check_icount(argv[0]))
return;
if (parse_inode(argv[0], "inode", argv[1], &ino))
return;
retval = ext2fs_icount_decrement(test_icount, ino, &count);
if (retval) {
com_err(argv[0], retval,
"while calling ext2fs_icount_increment");
return;
}
printf("Count is now %u\n", count);
}
void do_store(int argc, char **argv)
{
const char *usage = "usage: %s inode count";
errcode_t retval;
ino_t ino;
ino_t count;
if (argc < 3) {
printf(usage, argv[0]);
return;
}
if (check_icount(argv[0]))
return;
if (parse_inode(argv[0], "inode", argv[1], &ino))
return;
if (parse_inode(argv[0], "count", argv[2], &count))
return;
if (count > 65535) {
printf("Count too large.\n");
return;
}
retval = ext2fs_icount_store(test_icount, ino, (__u16) count);
if (retval) {
com_err(argv[0], retval,
"while calling ext2fs_icount_store");
return;
}
}
void do_dump(int argc, char **argv)
{
errcode_t retval;
ino_t i;
__u16 count;
if (check_icount(argv[0]))
return;
for (i=1; i <= test_fs->super->s_inodes_count; i++) {
retval = ext2fs_icount_fetch(test_icount, i, &count);
if (retval) {
com_err(argv[0], retval,
"while fetching icount for %lu", i);
return;
}
if (count)
printf("%lu: %u\n", i, count);
}
}
void do_validate(int argc, char **argv)
{
errcode_t retval;
ino_t size;
if (check_icount(argv[0]))
return;
retval = ext2fs_icount_validate(test_icount, stdout);
if (retval) {
com_err(argv[0], retval, "while validating icount structure");
return;
}
printf("Icount structure successfully validated\n");
}
void do_get_size(int argc, char **argv)
{
errcode_t retval;
ino_t size;
if (check_icount(argv[0]))
return;
size = ext2fs_get_icount_size(test_icount);
printf("Size of icount is: %u\n", size);
}
static int source_file(const char *cmd_file, int sci_idx)
{
FILE *f;
char buf[256];
char *cp;
int exit_status = 0;
int retval;
int noecho;
if (strcmp(cmd_file, "-") == 0)
f = stdin;
else {
f = fopen(cmd_file, "r");
if (!f) {
perror(cmd_file);
exit(1);
}
}
setbuf(stdout, NULL);
setbuf(stderr, NULL);
while (!feof(f)) {
if (fgets(buf, sizeof(buf), f) == NULL)
break;
if (buf[0] == '#')
continue;
noecho = 0;
if (buf[0] == '-') {
noecho = 1;
buf[0] = ' ';
}
cp = strchr(buf, '\n');
if (cp)
*cp = 0;
cp = strchr(buf, '\r');
if (cp)
*cp = 0;
if (!noecho)
printf("test_icount: %s\n", buf);
retval = ss_execute_line(sci_idx, buf);
if (retval) {
ss_perror(sci_idx, retval, buf);
exit_status++;
}
}
return exit_status;
}
void main(int argc, char **argv)
{
int retval;
int sci_idx;
const char *usage = "Usage: test_icount [-R request] [-f cmd_file]";
char c;
char *request = 0;
int exit_status = 0;
char *cmd_file = 0;
struct ext2_super_block param;
initialize_ext2_error_table();
/*
* Create a sample filesystem structure
*/
memset(&param, 0, sizeof(struct ext2_super_block));
param.s_blocks_count = 80000;
param.s_inodes_count = 20000;
retval = ext2fs_initialize("/dev/null", 0, &param,
unix_io_manager, &test_fs);
if (retval) {
com_err("/dev/null", retval, "while setting up test fs");
exit(1);
}
while ((c = getopt (argc, argv, "wR:f:")) != EOF) {
switch (c) {
case 'R':
request = optarg;
break;
case 'f':
cmd_file = optarg;
break;
default:
com_err(argv[0], 0, usage);
return;
}
}
sci_idx = ss_create_invocation("test_icount", "0.0", (char *) NULL,
&test_cmds, &retval);
if (retval) {
ss_perror(sci_idx, retval, "creating invocation");
exit(1);
}
(void) ss_add_request_table (sci_idx, &ss_std_requests, 1, &retval);
if (retval) {
ss_perror(sci_idx, retval, "adding standard requests");
exit (1);
}
if (request) {
retval = 0;
retval = ss_execute_line(sci_idx, request);
if (retval) {
ss_perror(sci_idx, retval, request);
exit_status++;
}
} else if (cmd_file) {
exit_status = source_file(cmd_file, sci_idx);
} else {
ss_listen(sci_idx);
}
exit(exit_status);
}

View File

@ -0,0 +1,7 @@
void do_create_icount(int argc, char **argv);
void do_free_icount(int argc, char **argv);
void do_fetch(int argc, char **argv);
void do_increment(int argc, char **argv);
void do_decrement(int argc, char **argv);
void do_store(int argc, char **argv);
void do_get_size(int argc, char **argv);

View File

@ -0,0 +1,37 @@
#
# Copyright (C) 1997 Theodore Ts'o. This file may be redistributed
# under the terms of the GNU Public License.
#
command_table test_cmds;
#
# Icount table commands
#
request do_create_icount, "Create an icount structure",
create_icount, create;
request do_free_icount, "Free an icount structure",
free_icount, free;
request do_fetch, "Fetch an icount entry",
fetch;
request do_increment, "Increment an icount entry",
increment, inc;
request do_decrement, "Decrement an icount entry",
decrement, dec;
request do_store, "Store an icount entry",
store;
request do_get_size, "Get the size of the icount structure",
get_size;
request do_dump, "Dump the icount structure",
dump;
request do_validate, "Validate the icount structure",
validate, check;
end;

View File

@ -707,8 +707,6 @@ static int source_file(const char *cmd_file, int sci_idx)
return exit_status;
}
void main(int argc, char **argv)
{
int retval;

View File

@ -10,9 +10,12 @@ CHATTR=../misc/chattr
LSATTR=../misc/lsattr
DEBUGFS=../debugfs/debugfs
TEST_REL=../tests/progs/test_rel
TEST_ICOUNT=../tests/progs/test_icount
LD_LIBRARY_PATH=../lib:../lib/ext2fs:../lib/e2p:../lib/et:../lib/ss
TMPFILE=./test.img
export LD_LIBRARY_PATH
TZ=GMT
export TZ
LANG=C
export LANG
unset PAGER

View File

@ -9,7 +9,10 @@ else
TESTS=
for i
do
TESTS="$TESTS $SRCDIR/$i"
case $i in
[a-zA-Z]) TESTS="$TESTS $SRCDIR/${i}_*" ;;
*) TESTS="$TESTS $SRCDIR/$i" ;;
esac
done
fi