Merge branch 'maint' into next
diff --git a/Makefile.in b/Makefile.in
index 0f7aba3..54a0d14 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -10,7 +10,7 @@
@RESIZER_CMT@RESIZE_DIR= resize
@DEBUGFS_CMT@DEBUGFS_DIR= debugfs
-LIB_SUBDIRS=lib/et lib/ss lib/e2p lib/ext2fs lib/uuid lib/blkid intl
+LIB_SUBDIRS=lib/et lib/ss lib/e2p lib/uuid lib/ext2fs lib/blkid intl
PROG_SUBDIRS=e2fsck $(DEBUGFS_DIR) misc $(RESIZE_DIR) tests/progs po
SUBDIRS=util $(LIB_SUBDIRS) $(PROG_SUBDIRS) tests
diff --git a/configure b/configure
index dc4cac7..89e1611 100755
--- a/configure
+++ b/configure
@@ -684,7 +684,6 @@
LIB_EXT
STATIC_LIB_EXT
PROFILED_LIB_EXT
-SWAPFS_CMT
DEBUGFS_CMT
IMAGER_CMT
RESIZER_CMT
@@ -1371,7 +1370,6 @@
--enable-jbd-debug enable journal debugging
--enable-blkid-debug enable blkid debugging
--enable-testio-debug enable the use of the test I/O manager for debugging
- --disable-swapfs disable support of legacy byte-swapped filesystems
--disable-debugfs disable support of debugfs program
--disable-imager disable support of e2image program
--disable-resizer disable support of e2resize program
@@ -4000,32 +3998,6 @@
fi
-# Check whether --enable-swapfs was given.
-if test "${enable_swapfs+set}" = set; then
- enableval=$enable_swapfs; if test "$enableval" = "no"
-then
- SWAPFS_CMT=#
- echo "Disabling swapfs support"
-else
- SWAPFS_CMT=
- cat >>confdefs.h <<\_ACEOF
-#define ENABLE_SWAPFS 1
-_ACEOF
-
- echo "Enabling swapfs support"
-fi
-
-else
- SWAPFS_CMT=
-echo "Enabling swapfs support by default"
-cat >>confdefs.h <<\_ACEOF
-#define ENABLE_SWAPFS 1
-_ACEOF
-
-
-fi
-
-
# Check whether --enable-debugfs was given.
if test "${enable_debugfs+set}" = set; then
enableval=$enable_debugfs; if test "$enableval" = "no"
@@ -16035,11 +16007,11 @@
LIB_EXT!$LIB_EXT$ac_delim
STATIC_LIB_EXT!$STATIC_LIB_EXT$ac_delim
PROFILED_LIB_EXT!$PROFILED_LIB_EXT$ac_delim
-SWAPFS_CMT!$SWAPFS_CMT$ac_delim
DEBUGFS_CMT!$DEBUGFS_CMT$ac_delim
IMAGER_CMT!$IMAGER_CMT$ac_delim
RESIZER_CMT!$RESIZER_CMT$ac_delim
FSCK_PROG!$FSCK_PROG$ac_delim
+FSCK_MAN!$FSCK_MAN$ac_delim
_ACEOF
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 76; then
@@ -16109,7 +16081,6 @@
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
cat >conf$$subs.sed <<_ACEOF
-FSCK_MAN!$FSCK_MAN$ac_delim
E2INITRD_PROG!$E2INITRD_PROG$ac_delim
E2INITRD_MAN!$E2INITRD_MAN$ac_delim
PKG_CONFIG!$PKG_CONFIG$ac_delim
@@ -16194,7 +16165,7 @@
LTLIBOBJS!$LTLIBOBJS$ac_delim
_ACEOF
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 83; then
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 82; then
break
elif $ac_last_try; then
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
diff --git a/configure.in b/configure.in
index 157816e..5243549 100644
--- a/configure.in
+++ b/configure.in
@@ -367,26 +367,6 @@
echo "Disabling testio debugging by default"
)
dnl
-dnl handle --enable-swapfs
-dnl
-AC_ARG_ENABLE([swapfs],
-[ --disable-swapfs disable support of legacy byte-swapped filesystems],
-if test "$enableval" = "no"
-then
- SWAPFS_CMT=#
- echo "Disabling swapfs support"
-else
- SWAPFS_CMT=
- AC_DEFINE(ENABLE_SWAPFS)
- echo "Enabling swapfs support"
-fi
-,
-SWAPFS_CMT=
-echo "Enabling swapfs support by default"
-AC_DEFINE(ENABLE_SWAPFS)
-)
-AC_SUBST(SWAPFS_CMT)
-dnl
dnl handle --enable-debugfs
dnl
AC_ARG_ENABLE([debugfs],
diff --git a/debian/rules b/debian/rules
index df04b5e..4ba301c 100755
--- a/debian/rules
+++ b/debian/rules
@@ -103,7 +103,7 @@
${DEVMAPPER}
BF_CONF_FLAGS = --with-ccopts="${CCOPTS} ${BF_CCOPTS}" \
- --disable-nls --disable-swapfs --disable-imager \
+ --disable-nls --disable-imager \
--disable-uuidd --disable-tls \
--disable-debugfs --disable-e2initrd-helper
@@ -114,8 +114,7 @@
--with-ccopts=-fno-stack-protector
MIPS_NOPIC_CONF_FLAGS = --with-ccopts="${CCOPTS}" \
- --disable-nls \
- --disable-swapfs --disable-imager \
+ --disable-nls --disable-imager \
--disable-uuidd --disable-tls \
--disable-resizer # --disable-debugfs
diff --git a/debugfs/debugfs.8.in b/debugfs/debugfs.8.in
index 81b411e..9775438 100644
--- a/debugfs/debugfs.8.in
+++ b/debugfs/debugfs.8.in
@@ -306,7 +306,7 @@
.I \-b
options.
.TP
-.I ls [-l] [-d] filespec
+.I ls [-l] [-d] [-p] filespec
Print a listing of the files in the directory
.IR filespec .
The
@@ -315,6 +315,11 @@
The
.I \-d
flag will list deleted entries in the directory.
+The
+.I \-p
+flag will list the files in a format which is more easily parsable by
+scripts, as well as making it more clear when there are spaces or other
+non-prinitng characters at the end of filenames.
.TP
.I modify_inode filespec
Modify the contents of the inode structure in the inode
diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
index a92933d..95cc89c 100644
--- a/debugfs/debugfs.c
+++ b/debugfs/debugfs.c
@@ -38,6 +38,8 @@
#include "../version.h"
extern ss_request_table debug_cmds;
+ss_request_table *extra_cmds;
+const char *debug_prog_name;
ext2_filsys current_fs = NULL;
ext2_ino_t root, cwd;
@@ -286,7 +288,10 @@
FILE *out;
struct ext2_group_desc *gdp;
int c, header_only = 0;
- int numdirs = 0, first;
+ int numdirs = 0, first, gdt_csum;
+
+ gdt_csum = EXT2_HAS_RO_COMPAT_FEATURE(current_fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
reset_getopt();
while ((c = getopt (argc, argv, "h")) != EOF) {
@@ -322,7 +327,7 @@
"inode table at %u\n"
" %d free %s, "
"%d free %s, "
- "%d used %s\n",
+ "%d used %s%s",
i, gdp->bg_block_bitmap,
gdp->bg_inode_bitmap, gdp->bg_inode_table,
gdp->bg_free_blocks_count,
@@ -331,12 +336,21 @@
gdp->bg_free_inodes_count != 1 ? "inodes" : "inode",
gdp->bg_used_dirs_count,
gdp->bg_used_dirs_count != 1 ? "directories"
- : "directory");
+ : "directory", gdt_csum ? ", " : "\n");
+ if (gdt_csum)
+ fprintf(out, "%d unused %s\n",
+ gdp->bg_itable_unused,
+ gdp->bg_itable_unused != 1 ? "inodes":"inode");
first = 1;
print_bg_opts(gdp, EXT2_BG_INODE_UNINIT, "Inode not init",
&first, out);
print_bg_opts(gdp, EXT2_BG_BLOCK_UNINIT, "Block not init",
&first, out);
+ if (gdt_csum) {
+ fprintf(out, "%sChecksum 0x%04x",
+ first ? " [":", ", gdp->bg_checksum);
+ first = 0;
+ }
if (!first)
fputs("]\n", out);
}
@@ -509,7 +523,7 @@
lb.first_block = 0;
lb.f = f;
lb.first = 1;
- ext2fs_block_iterate2(current_fs, inode, 0, NULL,
+ ext2fs_block_iterate2(current_fs, inode, BLOCK_FLAG_READ_ONLY, NULL,
list_blocks_proc, (void *)&lb);
finish_range(&lb);
if (lb.total)
@@ -571,10 +585,6 @@
frag = inode->osd2.hurd2.h_i_frag;
fsize = inode->osd2.hurd2.h_i_fsize;
break;
- case EXT2_OS_MASIX:
- frag = inode->osd2.masix2.m_i_frag;
- fsize = inode->osd2.masix2.m_i_fsize;
- break;
default:
frag = fsize = 0;
}
@@ -791,7 +801,8 @@
sprintf(buf, format, *val);
printf("%30s [%s] ", prompt, buf);
- fgets(buf, sizeof(buf), stdin);
+ if (!fgets(buf, sizeof(buf), stdin))
+ return;
if (buf[strlen (buf) - 1] == '\n')
buf[strlen (buf) - 1] = '\0';
if (!buf[0])
@@ -812,7 +823,8 @@
sprintf(buf, format, *val);
printf("%30s [%s] ", prompt, buf);
- fgets(buf, sizeof(buf), stdin);
+ if (!fgets(buf, sizeof(buf), stdin))
+ return;
if (buf[strlen (buf) - 1] == '\n')
buf[strlen (buf) - 1] = '\0';
if (!buf[0])
@@ -833,7 +845,8 @@
sprintf(buf, format, *val);
printf("%30s [%s] ", prompt, buf);
- fgets(buf, sizeof(buf), stdin);
+ if (!fgets(buf, sizeof(buf), stdin))
+ return;
if (buf[strlen (buf) - 1] == '\n')
buf[strlen (buf) - 1] = '\0';
if (!buf[0])
@@ -901,10 +914,6 @@
frag = &inode.osd2.hurd2.h_i_frag;
fsize = &inode.osd2.hurd2.h_i_fsize;
break;
- case EXT2_OS_MASIX:
- frag = &inode.osd2.masix2.m_i_frag;
- fsize = &inode.osd2.masix2.m_i_fsize;
- break;
default:
frag = fsize = 0;
}
@@ -1013,7 +1022,7 @@
struct ext2_inode inode;
int retval;
ext2_ino_t dir;
- char *dest, *cp, *basename;
+ char *dest, *cp, *base_name;
/*
* Get the source inode
@@ -1021,17 +1030,17 @@
ino = string_to_inode(sourcename);
if (!ino)
return;
- basename = strrchr(sourcename, '/');
- if (basename)
- basename++;
+ base_name = strrchr(sourcename, '/');
+ if (base_name)
+ base_name++;
else
- basename = sourcename;
+ base_name = sourcename;
/*
* Figure out the destination. First see if it exists and is
* a directory.
*/
if (! (retval=ext2fs_namei(current_fs, root, cwd, destname, &dir)))
- dest = basename;
+ dest = base_name;
else {
/*
* OK, it doesn't exist. See if it is
@@ -1113,7 +1122,7 @@
if (debugfs_write_inode(ino, &inode, argv[0]))
return;
- ext2fs_block_iterate(current_fs, ino, 0, NULL,
+ ext2fs_block_iterate(current_fs, ino, BLOCK_FLAG_READ_ONLY, NULL,
mark_blocks_proc, NULL);
ext2fs_inode_alloc_stats2(current_fs, ino, +1, 0);
@@ -1126,19 +1135,19 @@
{
int retval;
ext2_ino_t dir;
- char *basename;
+ char *base_name;
- basename = strrchr(filename, '/');
- if (basename) {
- *basename++ = '\0';
+ base_name = strrchr(filename, '/');
+ if (base_name) {
+ *base_name++ = '\0';
dir = string_to_inode(filename);
if (!dir)
return;
} else {
dir = cwd;
- basename = filename;
+ base_name = filename;
}
- retval = ext2fs_unlink(current_fs, dir, basename, 0, 0);
+ retval = ext2fs_unlink(current_fs, dir, base_name, 0, 0);
if (retval)
com_err("unlink_file_by_name", retval, 0);
return;
@@ -1511,7 +1520,7 @@
if (!ext2fs_inode_has_valid_blocks(&inode_buf))
return;
- ext2fs_block_iterate(current_fs, inode, 0, NULL,
+ ext2fs_block_iterate(current_fs, inode, BLOCK_FLAG_READ_ONLY, NULL,
release_blocks_proc, NULL);
printf("\n");
ext2fs_inode_alloc_stats2(current_fs, inode, -1,
@@ -1810,7 +1819,7 @@
{
int retval;
int sci_idx;
- const char *usage = "Usage: debugfs [-b blocksize] [-s superblock] [-f cmd_file] [-R request] [-V] [[-w] [-c] device]";
+ const char *usage = "Usage: %s [-b blocksize] [-s superblock] [-f cmd_file] [-R request] [-V] [[-w] [-c] device]";
int c;
int open_flags = EXT2_FLAG_SOFTSUPP_FEATURES;
char *request = 0;
@@ -1821,9 +1830,12 @@
int catastrophic = 0;
char *data_filename = 0;
+ if (debug_prog_name == 0)
+ debug_prog_name = "debugfs";
+
add_error_table(&et_ext2_error_table);
- fprintf (stderr, "debugfs %s (%s)\n", E2FSPROGS_VERSION,
- E2FSPROGS_DATE);
+ fprintf (stderr, "%s %s (%s)\n", debug_prog_name,
+ E2FSPROGS_VERSION, E2FSPROGS_DATE);
while ((c = getopt (argc, argv, "iwcR:f:b:s:Vd:")) != EOF) {
switch (c) {
@@ -1859,7 +1871,7 @@
error_message(EXT2_ET_BASE));
exit(0);
default:
- com_err(argv[0], 0, usage);
+ com_err(argv[0], 0, usage, debug_prog_name);
return 1;
}
}
@@ -1868,7 +1880,7 @@
superblock, blocksize, catastrophic,
data_filename);
- sci_idx = ss_create_invocation("debugfs", "0.0", (char *) NULL,
+ sci_idx = ss_create_invocation(debug_prog_name, "0.0", (char *) NULL,
&debug_cmds, &retval);
if (retval) {
ss_perror(sci_idx, retval, "creating invocation");
@@ -1881,6 +1893,12 @@
ss_perror(sci_idx, retval, "adding standard requests");
exit (1);
}
+ if (extra_cmds)
+ ss_add_request_table (sci_idx, extra_cmds, 1, &retval);
+ if (retval) {
+ ss_perror(sci_idx, retval, "adding extra requests");
+ exit (1);
+ }
if (request) {
retval = 0;
retval = ss_execute_line(sci_idx, request);
diff --git a/debugfs/debugfs.h b/debugfs/debugfs.h
index d72c7ac..003c19a 100644
--- a/debugfs/debugfs.h
+++ b/debugfs/debugfs.h
@@ -78,6 +78,7 @@
/* set_fields.c */
extern void do_set_super(int argc, char **);
extern void do_set_inode(int argc, char **);
+extern void do_set_block_group_descriptor(int argc, char **);
/* unused.c */
extern void do_dump_unused(int argc, char **argv);
diff --git a/debugfs/htree.c b/debugfs/htree.c
index d0e673e..a46bae7 100644
--- a/debugfs/htree.c
+++ b/debugfs/htree.c
@@ -347,7 +347,8 @@
pb.search_name = argv[2];
pb.len = strlen(pb.search_name);
- ext2fs_block_iterate2(current_fs, inode, 0, 0, search_dir_block, &pb);
+ ext2fs_block_iterate2(current_fs, inode, BLOCK_FLAG_READ_ONLY, 0,
+ search_dir_block, &pb);
free(pb.buf);
}
diff --git a/debugfs/icheck.c b/debugfs/icheck.c
index a6b182d..01c78bc 100644
--- a/debugfs/icheck.c
+++ b/debugfs/icheck.c
@@ -127,7 +127,8 @@
if (inode.i_dtime)
goto next;
- retval = ext2fs_block_iterate2(current_fs, ino, 0, block_buf,
+ retval = ext2fs_block_iterate2(current_fs, ino,
+ BLOCK_FLAG_READ_ONLY, block_buf,
icheck_proc, &bw);
if (retval) {
com_err("icheck", retval,
diff --git a/debugfs/logdump.c b/debugfs/logdump.c
index 2bf67b5..08e58f7 100644
--- a/debugfs/logdump.c
+++ b/debugfs/logdump.c
@@ -36,11 +36,11 @@
enum journal_location {JOURNAL_IS_INTERNAL, JOURNAL_IS_EXTERNAL};
-#define ANY_BLOCK ((unsigned int) -1)
+#define ANY_BLOCK ((blk_t) -1)
int dump_all, dump_contents, dump_descriptors;
-unsigned int block_to_dump, group_to_dump, bitmap_to_dump;
-unsigned int inode_block_to_dump, inode_offset_to_dump, bitmap_to_dump;
+blk_t block_to_dump, bitmap_to_dump, inode_block_to_dump;
+unsigned int group_to_dump, inode_offset_to_dump;
ext2_ino_t inode_to_dump;
struct journal_source
@@ -350,7 +350,7 @@
jsb = (journal_superblock_t *) buf;
sb = (struct ext2_super_block *) (buf+1024);
-#ifdef ENABLE_SWAPFS
+#ifdef WORDS_BIGENDIAN
if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
ext2fs_swap_super(sb);
#endif
@@ -365,8 +365,8 @@
if (dump_all) {
fprintf(out_file, "\tuuid=%s\n", jsb_buffer);
fprintf(out_file, "\tblocksize=%d\n", blocksize);
- fprintf(out_file, "\tjournal data size %ld\n",
- (long) sb->s_blocks_count);
+ fprintf(out_file, "\tjournal data size %lu\n",
+ (unsigned long) sb->s_blocks_count);
}
}
diff --git a/debugfs/ls.c b/debugfs/ls.c
index 52c7e34..1ceeb1b 100644
--- a/debugfs/ls.c
+++ b/debugfs/ls.c
@@ -30,6 +30,7 @@
#define LONG_OPT 0x0001
#define DELETED_OPT 0x0002
+#define PARSE_OPT 0x0004
struct list_dir_struct {
FILE *f;
@@ -72,7 +73,16 @@
} else {
lbr = rbr = ' ';
}
- if (ls->options & LONG_OPT) {
+ if (ls->options & PARSE_OPT) {
+ if (ino && debugfs_read_inode(ino, &inode, name)) return 0;
+ fprintf(ls->f,"/%u/%06o/%d/%d/%s/",ino,inode.i_mode,inode.i_uid, inode.i_gid,name);
+ if (LINUX_S_ISDIR(inode.i_mode))
+ fprintf(ls->f, "/");
+ else
+ fprintf(ls->f, "%lld/", inode.i_size | ((__u64)inode.i_size_high << 32));
+ fprintf(ls->f, "\n");
+ }
+ else if (ls->options & LONG_OPT) {
if (ino) {
if (debugfs_read_inode(ino, &inode, name))
return 0;
@@ -123,7 +133,7 @@
return;
reset_getopt();
- while ((c = getopt (argc, argv, "dl")) != EOF) {
+ while ((c = getopt (argc, argv, "dlp")) != EOF) {
switch (c) {
case 'l':
ls.options |= LONG_OPT;
@@ -131,6 +141,9 @@
case 'd':
ls.options |= DELETED_OPT;
break;
+ case 'p':
+ ls.options |= PARSE_OPT;
+ break;
default:
goto print_usage;
}
@@ -138,7 +151,7 @@
if (argc > optind+1) {
print_usage:
- com_err(0, 0, "Usage: ls [-l] [-d] file");
+ com_err(0, 0, "Usage: ls [-l] [-d] [-p] file");
return;
}
diff --git a/debugfs/lsdel.c b/debugfs/lsdel.c
index b3293b8..f703c6b 100644
--- a/debugfs/lsdel.c
+++ b/debugfs/lsdel.c
@@ -140,7 +140,8 @@
lsd.free_blocks = 0;
lsd.bad_blocks = 0;
- retval = ext2fs_block_iterate2(current_fs, ino, 0, block_buf,
+ retval = ext2fs_block_iterate2(current_fs, ino,
+ BLOCK_FLAG_READ_ONLY, block_buf,
lsdel_proc, &lsd);
if (retval) {
com_err("ls_deleted_inodes", retval,
diff --git a/debugfs/set_fields.c b/debugfs/set_fields.c
index 454a3db..ee51c45 100644
--- a/debugfs/set_fields.c
+++ b/debugfs/set_fields.c
@@ -29,6 +29,9 @@
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
+#if HAVE_STRINGS_H
+#include <strings.h>
+#endif
#include <fcntl.h>
#include <utime.h>
@@ -39,6 +42,7 @@
static struct ext2_super_block set_sb;
static struct ext2_inode set_inode;
static struct ext2_group_desc set_gd;
+static dgrp_t set_bg;
static ext2_ino_t set_ino;
static int array_idx;
@@ -60,6 +64,7 @@
static errcode_t parse_hashalg(struct field_set_info *info, char *arg);
static errcode_t parse_time(struct field_set_info *info, char *arg);
static errcode_t parse_bmap(struct field_set_info *info, char *arg);
+static errcode_t parse_gd_csum(struct field_set_info *info, char *arg);
static struct field_set_info super_fields[] = {
{ "inodes_count", &set_sb.s_inodes_count, 4, parse_uint },
@@ -175,7 +180,7 @@
{ "flags", &set_gd.bg_flags, 2, parse_uint },
{ "reserved", &set_gd.bg_reserved, 2, parse_uint, FLAG_ARRAY, 2 },
{ "itable_unused", &set_gd.bg_itable_unused, 2, parse_uint },
- { "checksum", &set_gd.bg_checksum, 2, parse_uint },
+ { "checksum", &set_gd.bg_checksum, 2, parse_gd_csum },
{ 0, 0, 0, 0 }
};
@@ -399,6 +404,19 @@
return retval;
}
+static errcode_t parse_gd_csum(struct field_set_info *info, char *arg)
+{
+
+ if (strcmp(arg, "calc") == 0) {
+ ext2fs_group_desc_csum_set(current_fs, set_bg);
+ set_gd = current_fs->group_desc[set_bg];
+ printf("Checksum set to 0x%04x\n",
+ current_fs->group_desc[set_bg].bg_checksum);
+ return 0;
+ }
+
+ return parse_uint(info, arg);
+}
static void print_possible_fields(struct field_set_info *fields)
{
@@ -518,7 +536,6 @@
"\t\"set_block_group_descriptor -l\" will list the names of "
"the fields in a block group descriptor\n\twhich can be set.";
struct field_set_info *ss;
- dgrp_t set_bg;
char *end;
if ((argc == 2) && !strcmp(argv[1], "-l")) {
diff --git a/debugfs/util.c b/debugfs/util.c
index ebce9d6..28abe52 100644
--- a/debugfs/util.c
+++ b/debugfs/util.c
@@ -123,7 +123,7 @@
retval = ext2fs_namei(current_fs, root, cwd, str, &ino);
if (retval) {
- com_err(str, retval, "");
+ com_err(str, retval, 0);
return 0;
}
return ino;
@@ -192,7 +192,7 @@
{
static int do_gmt = -1;
time_t t = (time_t) cl;
- char * tz;
+ const char *tz;
if (do_gmt == -1) {
/* The diet libc doesn't respect the TZ environemnt variable */
@@ -277,10 +277,8 @@
blk = parse_ulong(str, cmd, "block number", &err);
*ret = blk;
- if (err == 0 && blk == 0) {
- com_err(cmd, 0, "Invalid block number 0");
- err = 1;
- }
+ if (err)
+ com_err(cmd, 0, "Invalid block number: %s", str);
return err;
}
@@ -340,6 +338,11 @@
if (strtoblk(argv[0], argv[1], block))
return 1;
+ if (*block == 0) {
+ com_err(argv[0], 0, "Invalid block number 0");
+ err = 1;
+ }
+
if (argc > 2) {
*count = parse_ulong(argv[2], argv[0], "count", &err);
if (err)
diff --git a/doc/libext2fs.texinfo b/doc/libext2fs.texinfo
index f3b0d1e..bfe8971 100644
--- a/doc/libext2fs.texinfo
+++ b/doc/libext2fs.texinfo
@@ -7,11 +7,9 @@
@ifinfo
@dircategory Development
-@format
-START-INFO-DIR-ENTRY
+@direntry
* libext2fs: (libext2fs.info). The EXT2FS library.
-END-INFO-DIR-ENTRY
-@end format
+@end direntry
@end ifinfo
@c smallbook
diff --git a/e2fsck/Makefile.in b/e2fsck/Makefile.in
index d5a8887..be6dfb7 100644
--- a/e2fsck/Makefile.in
+++ b/e2fsck/Makefile.in
@@ -62,7 +62,7 @@
#MCHECK= -DMCHECK
OBJS= dict.o unix.o e2fsck.o super.o pass1.o pass1b.o pass2.o pass3.o pass4.o \
- pass5.o journal.o swapfs.o badblocks.o util.o dirinfo.o dx_dirinfo.o \
+ pass5.o journal.o badblocks.o util.o dirinfo.o dx_dirinfo.o \
ehandler.o problem.o message.o recovery.o region.o revoke.o \
ea_refcount.o rehash.o profile.o prof_err.o $(MTRACE_OBJ)
@@ -71,7 +71,7 @@
profiled/pass2.o profiled/pass3.o profiled/pass4.o profiled/pass5.o \
profiled/journal.o profiled/badblocks.o profiled/util.o \
profiled/dirinfo.o profiled/dx_dirinfo.o profiled/ehandler.o \
- profiled/message.o profiled/problem.o profiled/swapfs.o \
+ profiled/message.o profiled/problem.o \
profiled/recovery.o profiled/region.o profiled/revoke.o \
profiled/ea_refcount.o profiled/rehash.o profiled/profile.o \
profiled/prof_err.o
@@ -96,7 +96,6 @@
$(srcdir)/ehandler.c \
$(srcdir)/problem.c \
$(srcdir)/message.c \
- $(srcdir)/swapfs.c \
$(srcdir)/ea_refcount.c \
$(srcdir)/rehash.c \
$(srcdir)/region.c \
@@ -378,13 +377,6 @@
$(top_builddir)/lib/ext2fs/ext2_err.h $(top_srcdir)/lib/ext2fs/bitops.h \
$(top_srcdir)/lib/blkid/blkid.h $(top_builddir)/lib/blkid/blkid_types.h \
$(srcdir)/profile.h prof_err.h $(srcdir)/problem.h
-swapfs.o: $(srcdir)/swapfs.c $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/e2fsck.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
- $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
- $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_srcdir)/lib/ext2fs/ext2_io.h \
- $(top_builddir)/lib/ext2fs/ext2_err.h $(top_srcdir)/lib/ext2fs/bitops.h \
- $(top_srcdir)/lib/blkid/blkid.h $(top_builddir)/lib/blkid/blkid_types.h \
- $(srcdir)/profile.h prof_err.h
ea_refcount.o: $(srcdir)/ea_refcount.c $(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
diff --git a/e2fsck/e2fsck.8.in b/e2fsck/e2fsck.8.in
index 3059e60..53c473e 100644
--- a/e2fsck/e2fsck.8.in
+++ b/e2fsck/e2fsck.8.in
@@ -8,7 +8,7 @@
.SH SYNOPSIS
.B e2fsck
[
-.B \-pacnyrdfkvstDFSV
+.B \-pacnyrdfkvtDFV
]
[
.B \-b
@@ -279,17 +279,6 @@
.B \-r
This option does nothing at all; it is provided only for backwards
compatibility.
-.TP
-.B \-s
-This option will byte-swap the filesystem so that it is using the normalized,
-standard byte-order (which is i386 or little endian). If the filesystem is
-already in the standard byte-order,
-.B e2fsck
-will take no action.
-.TP
-.B \-S
-This option will byte-swap the filesystem, regardless of its current
-byte-order.
.TP
.B \-t
Print timing statistics for
diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h
index 5af82d5..bd173af 100644
--- a/e2fsck/e2fsck.h
+++ b/e2fsck/e2fsck.h
@@ -135,6 +135,8 @@
struct timeval user_start;
struct timeval system_start;
void *brk_start;
+ unsigned long long bytes_read;
+ unsigned long long bytes_written;
};
#endif
@@ -427,8 +429,11 @@
extern void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
extern int e2fsck_pass1_check_device_inode(ext2_filsys fs,
struct ext2_inode *inode);
-extern int e2fsck_pass1_check_symlink(ext2_filsys fs,
+extern int e2fsck_pass1_check_symlink(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode, char *buf);
+extern void e2fsck_clear_inode(e2fsck_t ctx, ext2_ino_t ino,
+ struct ext2_inode *inode, int restart_flag,
+ const char *source);
/* pass2.c */
extern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
@@ -456,9 +461,6 @@
void check_super_block(e2fsck_t ctx);
int check_backup_super_block(e2fsck_t ctx);
-/* swapfs.c */
-void swap_filesys(e2fsck_t ctx);
-
/* util.c */
extern void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
const char *description);
@@ -469,14 +471,21 @@
extern void e2fsck_write_bitmaps(e2fsck_t ctx);
extern void preenhalt(e2fsck_t ctx);
extern char *string_copy(e2fsck_t ctx, const char *str, int len);
+extern errcode_t e2fsck_zero_blocks(ext2_filsys fs, blk_t blk, int num,
+ blk_t *ret_blk, int *ret_count);
#ifdef RESOURCE_TRACK
extern void print_resource_track(const char *desc,
- struct resource_track *track);
-extern void init_resource_track(struct resource_track *track);
+ struct resource_track *track,
+ io_channel channel);
+extern void init_resource_track(struct resource_track *track,
+ io_channel channel);
#endif
extern int inode_has_valid_blocks(struct ext2_inode *inode);
extern void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
struct ext2_inode * inode, const char * proc);
+extern void e2fsck_read_inode_full(e2fsck_t ctx, unsigned long ino,
+ struct ext2_inode *inode,
+ const int bufsize, const char *proc);
extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
struct ext2_inode * inode, const char * proc);
extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
diff --git a/e2fsck/journal.c b/e2fsck/journal.c
index dbe1bf1..ec0af4b 100644
--- a/e2fsck/journal.c
+++ b/e2fsck/journal.c
@@ -385,7 +385,7 @@
memcpy(&jsuper, start ? bh->b_data : bh->b_data + 1024,
sizeof(jsuper));
brelse(bh);
-#ifdef EXT2FS_ENABLE_SWAPFS
+#ifdef WORDS_BIGENDIAN
if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
ext2fs_swap_super(&jsuper);
#endif
@@ -988,6 +988,7 @@
ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
ext2fs_mark_ib_dirty(fs);
fs->group_desc[group].bg_free_inodes_count++;
+ ext2fs_group_desc_csum_set(fs, group);
fs->super->s_free_inodes_count++;
return;
diff --git a/e2fsck/message.c b/e2fsck/message.c
index b2e3e0f..8a3705e 100644
--- a/e2fsck/message.c
+++ b/e2fsck/message.c
@@ -80,6 +80,7 @@
* @S superblock
* @u unattached
* @v device
+ * @x extent
* @z zero-length
*/
@@ -134,6 +135,7 @@
N_("Ssuper@b"),
N_("uunattached"),
N_("vdevice"),
+ N_("xextent"),
N_("zzero-length"),
"@@",
0
@@ -388,7 +390,11 @@
fputc('%', stdout);
break;
case 'b':
- printf("%u", ctx->blk);
+#ifdef EXT2_NO_64_TYPE
+ printf("%u", (unsigned long) ctx->blk);
+#else
+ printf("%llu", (unsigned long long) ctx->blk);
+#endif
break;
case 'B':
#ifdef EXT2_NO_64_TYPE
@@ -398,7 +404,11 @@
#endif
break;
case 'c':
- printf("%u", ctx->blk2);
+#ifdef EXT2_NO_64_TYPE
+ printf("%u", (unsigned long) ctx->blk2);
+#else
+ printf("%llu", (unsigned long long) ctx->blk2);
+#endif
break;
case 'd':
printf("%u", ctx->dir);
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index 839f099..b85f04f 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -163,17 +163,42 @@
* Check to make sure a symlink inode is real. Returns 1 if the symlink
* checks out, 0 if not.
*/
-int e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode,
- char *buf)
+int e2fsck_pass1_check_symlink(ext2_filsys fs, ext2_ino_t ino,
+ struct ext2_inode *inode, char *buf)
{
unsigned int len;
int i;
blk_t blocks;
+ ext2_extent_handle_t handle;
+ struct ext2_extent_info info;
+ struct ext2fs_extent extent;
if ((inode->i_size_high || inode->i_size == 0) ||
(inode->i_flags & EXT2_INDEX_FL))
return 0;
+ if (inode->i_flags & EXT4_EXTENTS_FL) {
+ if (inode->i_size > fs->blocksize)
+ return 0;
+ if (ext2fs_extent_open(fs, ino, &handle))
+ return 0;
+ i = 0;
+ if (ext2fs_extent_get_info(handle, &info) ||
+ (info.num_entries != 1) ||
+ (info.max_depth != 0))
+ goto exit_extent;
+ if (ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent) ||
+ (extent.e_lblk != 0) ||
+ (extent.e_len != 1) ||
+ (extent.e_pblk < fs->super->s_first_data_block) ||
+ (extent.e_pblk >= fs->super->s_blocks_count))
+ goto exit_extent;
+ i = 1;
+ exit_extent:
+ ext2fs_extent_free(handle);
+ return i;
+ }
+
blocks = ext2fs_inode_data_blocks(fs, inode);
if (blocks) {
if ((inode->i_size >= fs->blocksize) ||
@@ -264,6 +289,7 @@
remain = storage_size - sizeof(__u32);
while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
+ __u32 hash;
/* header eats this space */
remain -= sizeof(struct ext2_ext_attr_entry);
@@ -291,9 +317,12 @@
problem = PR_1_ATTR_VALUE_BLOCK;
goto fix;
}
-
- /* e_hash must be 0 in inode's ea */
- if (entry->e_hash != 0) {
+
+ hash = ext2fs_ext_attr_hash_entry(entry,
+ start + entry->e_value_offs);
+
+ /* e_hash may be 0 in older inode's ea */
+ if (entry->e_hash != 0 && entry->e_hash != hash) {
pctx->num = entry->e_hash;
problem = PR_1_ATTR_HASH;
goto fix;
@@ -308,15 +337,12 @@
* it seems like a corruption. it's very unlikely we could repair
* EA(s) in automatic fashion -bzzz
*/
-#if 0
- problem = PR_1_ATTR_HASH;
-#endif
if (problem == 0 || !fix_problem(ctx, problem, pctx))
return;
- /* simple remove all possible EA(s) */
+ /* simply remove all possible EA(s) */
*((__u32 *)start) = 0UL;
- e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *) inode,
+ e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
EXT2_INODE_SIZE(sb), "pass1");
}
@@ -480,12 +506,12 @@
struct scan_callback_struct scan_struct;
struct ext2_super_block *sb = ctx->fs->super;
const char *old_op;
- int imagic_fs;
+ int imagic_fs, extent_fs;
int busted_fs_time = 0;
int inode_size;
#ifdef RESOURCE_TRACK
- init_resource_track(&rtrack);
+ init_resource_track(&rtrack, ctx->fs->io);
#endif
clear_problem_context(&pctx);
@@ -514,6 +540,7 @@
#undef EXT2_BPP
imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
+ extent_fs = (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS);
/*
* Allocate bitmaps structures
@@ -653,6 +680,76 @@
return;
}
}
+
+ /*
+ * Test for incorrect extent flag settings.
+ *
+ * On big-endian machines we must be careful:
+ * When the inode is read, the i_block array is not swapped
+ * if the extent flag is set. Therefore if we are testing
+ * for or fixing a wrongly-set flag, we must potentially
+ * (un)swap before testing, or after fixing.
+ */
+
+ /*
+ * In this case the extents flag was set when read, so
+ * extent_header_verify is ok. If the inode is cleared,
+ * no need to swap... so no extra swapping here.
+ */
+ if ((inode->i_flags & EXT4_EXTENTS_FL) && !extent_fs &&
+ (inode->i_links_count || (ino == EXT2_BAD_INO) ||
+ (ino == EXT2_ROOT_INO) || (ino == EXT2_JOURNAL_INO))) {
+ if ((ext2fs_extent_header_verify(inode->i_block,
+ sizeof(inode->i_block)) == 0) &&
+ fix_problem(ctx, PR_1_EXTENT_FEATURE, &pctx)) {
+ sb->s_feature_incompat |= EXT3_FEATURE_INCOMPAT_EXTENTS;
+ ext2fs_mark_super_dirty(fs);
+ extent_fs = 1;
+ } else if (fix_problem(ctx, PR_1_EXTENTS_SET, &pctx)) {
+ clear_inode:
+ e2fsck_clear_inode(ctx, ino, inode, 0, "pass1");
+ if (ino == EXT2_BAD_INO)
+ ext2fs_mark_inode_bitmap(ctx->inode_used_map,
+ ino);
+ continue;
+ }
+ }
+
+ /*
+ * For big-endian machines:
+ * If the inode didn't have the extents flag set when it
+ * was read, then the i_blocks array was swapped. To test
+ * as an extents header, we must swap it back first.
+ * IF we then set the extents flag, the entire i_block
+ * array must be un/re-swapped to make it proper extents data.
+ */
+ if (extent_fs && !(inode->i_flags & EXT4_EXTENTS_FL) &&
+ (inode->i_links_count || (ino == EXT2_BAD_INO) ||
+ (ino == EXT2_ROOT_INO) || (ino == EXT2_JOURNAL_INO)) &&
+ (LINUX_S_ISREG(inode->i_mode) ||
+ LINUX_S_ISDIR(inode->i_mode))) {
+ void *ehp;
+#ifdef WORDS_BIGENDIAN
+ __u32 tmp_block[EXT2_N_BLOCKS];
+
+ for (i = 0; i < EXT2_N_BLOCKS; i++)
+ tmp_block[i] = ext2fs_swab32(inode->i_block[i]);
+ ehp = tmp_block;
+#else
+ ehp = inode->i_block;
+#endif
+ if ((ext2fs_extent_header_verify(ehp,
+ sizeof(inode->i_block)) == 0) &&
+ (fix_problem(ctx, PR_1_UNSET_EXTENT_FL, &pctx))) {
+ inode->i_flags |= EXT4_EXTENTS_FL;
+#ifdef WORDS_BIGENDIAN
+ memcpy(inode->i_block, tmp_block,
+ sizeof(inode->i_block));
+#endif
+ e2fsck_write_inode(ctx, ino, inode, "pass1");
+ }
+ }
+
if (ino == EXT2_BAD_INO) {
struct process_block_struct pb;
@@ -695,15 +792,8 @@
* regnerated in pass #3.
*/
if (!LINUX_S_ISDIR(inode->i_mode)) {
- if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
- inode->i_dtime = ctx->now;
- inode->i_links_count = 0;
- ext2fs_icount_store(ctx->inode_link_info,
- ino, 0);
- e2fsck_write_inode(ctx, ino, inode,
- "pass1");
- }
-
+ if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx))
+ goto clear_inode;
}
/*
* If dtime is set, offer to clear it. mke2fs
@@ -834,10 +924,6 @@
frag = inode->osd2.hurd2.h_i_frag;
fsize = inode->osd2.hurd2.h_i_fsize;
break;
- case EXT2_OS_MASIX:
- frag = inode->osd2.masix2.m_i_frag;
- fsize = inode->osd2.masix2.m_i_fsize;
- break;
default:
frag = fsize = 0;
}
@@ -868,6 +954,18 @@
check_inode_extra_space(ctx, &pctx);
check_is_really_dir(ctx, &pctx, block_buf);
+ /*
+ * ext2fs_inode_has_valid_blocks does not actually look
+ * at i_block[] values, so not endian-sensitive here.
+ */
+ if (extent_fs && (inode->i_flags & EXT4_EXTENTS_FL) &&
+ LINUX_S_ISLNK(inode->i_mode) &&
+ !ext2fs_inode_has_valid_blocks(inode) &&
+ fix_problem(ctx, PR_1_FAST_SYMLINK_EXTENT_FL, &pctx)) {
+ inode->i_flags &= ~EXT4_EXTENTS_FL;
+ e2fsck_write_inode(ctx, ino, inode, "pass1");
+ }
+
if (LINUX_S_ISDIR(inode->i_mode)) {
ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
e2fsck_add_dir_info(ctx, ino, 0);
@@ -886,7 +984,8 @@
check_size(ctx, &pctx);
ctx->fs_blockdev_count++;
} else if (LINUX_S_ISLNK (inode->i_mode) &&
- e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
+ e2fsck_pass1_check_symlink(fs, ino, inode,
+ block_buf)) {
check_immutable(ctx, &pctx);
ctx->fs_symlinks_count++;
if (ext2fs_inode_data_blocks(fs, inode) == 0) {
@@ -913,10 +1012,11 @@
ctx->fs_dind_count++;
if (inode->i_block[EXT2_TIND_BLOCK])
ctx->fs_tind_count++;
- if (inode->i_block[EXT2_IND_BLOCK] ||
- inode->i_block[EXT2_DIND_BLOCK] ||
- inode->i_block[EXT2_TIND_BLOCK] ||
- inode->i_file_acl) {
+ if (!(inode->i_flags & EXT4_EXTENTS_FL) &&
+ (inode->i_block[EXT2_IND_BLOCK] ||
+ inode->i_block[EXT2_DIND_BLOCK] ||
+ inode->i_block[EXT2_TIND_BLOCK] ||
+ inode->i_file_acl)) {
inodes_to_process[process_inode_count].ino = ino;
inodes_to_process[process_inode_count].inode = *inode;
process_inode_count++;
@@ -1013,7 +1113,7 @@
#ifdef RESOURCE_TRACK
if (ctx->options & E2F_OPT_TIME2) {
e2fsck_clear_progbar(ctx);
- print_resource_track(_("Pass 1"), &rtrack);
+ print_resource_track(_("Pass 1"), &rtrack, ctx->fs->io);
}
#endif
}
@@ -1364,10 +1464,13 @@
entry = (struct ext2_ext_attr_entry *)(header+1);
end = block_buf + fs->blocksize;
while ((char *)entry < end && *(__u32 *)entry) {
+ __u32 hash;
+
if (region_allocate(region, (char *)entry - (char *)header,
EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
goto clear_extattr;
+ break;
}
if ((ctx->ext_attr_ver == 1 &&
(entry->e_name_len == 0 || entry->e_name_index != 0)) ||
@@ -1375,6 +1478,7 @@
entry->e_name_index == 0)) {
if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
goto clear_extattr;
+ break;
}
if (entry->e_value_block != 0) {
if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
@@ -1391,6 +1495,17 @@
if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
goto clear_extattr;
}
+
+ hash = ext2fs_ext_attr_hash_entry(entry, block_buf +
+ entry->e_value_offs);
+
+ if (entry->e_hash != hash) {
+ pctx->num = entry->e_hash;
+ if (fix_problem(ctx, PR_1_ATTR_HASH, pctx))
+ goto clear_extattr;
+ entry->e_hash = hash;
+ }
+
entry = EXT2_EXT_ATTR_NEXT(entry);
}
if (region_allocate(region, (char *)entry - (char *)header, 4)) {
@@ -1416,8 +1531,7 @@
/* Returns 1 if bad htree, 0 if OK */
static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
- ext2_ino_t ino EXT2FS_ATTR((unused)),
- struct ext2_inode *inode,
+ ext2_ino_t ino, struct ext2_inode *inode,
char *block_buf)
{
struct ext2_dx_root_info *root;
@@ -1431,12 +1545,17 @@
fix_problem(ctx, PR_1_HTREE_SET, pctx)))
return 1;
- blk = inode->i_block[0];
- if (((blk == 0) ||
- (blk < fs->super->s_first_data_block) ||
- (blk >= fs->super->s_blocks_count)) &&
- fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
- return 1;
+ pctx->errcode = ext2fs_bmap(fs, ino, inode, 0, 0, 0, &blk);
+
+ if ((pctx->errcode) ||
+ (blk == 0) ||
+ (blk < fs->super->s_first_data_block) ||
+ (blk >= fs->super->s_blocks_count)) {
+ if (fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
+ return 1;
+ else
+ return 0;
+ }
retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
@@ -1468,6 +1587,147 @@
return 0;
}
+void e2fsck_clear_inode(e2fsck_t ctx, ext2_ino_t ino,
+ struct ext2_inode *inode, int restart_flag,
+ const char *source)
+{
+ inode->i_flags = 0;
+ inode->i_links_count = 0;
+ ext2fs_icount_store(ctx->inode_link_info, ino, 0);
+ inode->i_dtime = ctx->now;
+
+ ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
+ ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
+ if (ctx->inode_reg_map)
+ ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
+ if (ctx->inode_bad_map)
+ ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
+
+ /*
+ * If the inode was partially accounted for before processing
+ * was aborted, we need to restart the pass 1 scan.
+ */
+ ctx->flags |= restart_flag;
+
+ e2fsck_write_inode(ctx, ino, inode, source);
+}
+
+static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,
+ struct process_block_struct *pb,
+ ext2_extent_handle_t ehandle)
+{
+ struct ext2fs_extent extent;
+ blk_t blk;
+ e2_blkcnt_t blockcnt;
+ int i;
+ int is_dir, is_leaf;
+ errcode_t problem;
+
+
+ pctx->errcode = ext2fs_extent_get(ehandle, EXT2_EXTENT_FIRST_SIB,
+ &extent);
+ while (!pctx->errcode) {
+ is_leaf = extent.e_flags & EXT2_EXTENT_FLAGS_LEAF;
+ is_dir = LINUX_S_ISDIR(pctx->inode->i_mode);
+
+ problem = 0;
+ if (extent.e_pblk < ctx->fs->super->s_first_data_block ||
+ extent.e_pblk >= ctx->fs->super->s_blocks_count)
+ problem = PR_1_EXTENT_BAD_START_BLK;
+ else if ((extent.e_pblk + extent.e_len) >
+ ctx->fs->super->s_blocks_count)
+ problem = PR_1_EXTENT_ENDS_BEYOND;
+
+ if (problem) {
+ pctx->blk = extent.e_pblk;
+ pctx->blk2 = extent.e_lblk;
+ pctx->num = extent.e_len;
+ if (fix_problem(ctx, problem, pctx)) {
+ pctx->errcode =
+ ext2fs_extent_delete(ehandle, 0);
+ if (pctx->errcode) {
+ fix_problem(ctx,
+ PR_1_EXTENT_DELETE_FAIL,
+ pctx);
+ /* Should never get here */
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
+ }
+ }
+ goto next;
+ }
+
+ if (!is_leaf) {
+ mark_block_used(ctx, extent.e_pblk);
+ pb->num_blocks++;
+ pctx->errcode = ext2fs_extent_get(ehandle,
+ EXT2_EXTENT_DOWN, &extent);
+ if (pctx->errcode) {
+ printf("Error1: %s on inode %lld\n",
+ error_message(pctx->errcode), pctx->ino);
+ abort();
+ }
+ scan_extent_node(ctx, pctx, pb, ehandle);
+ pctx->errcode = ext2fs_extent_get(ehandle,
+ EXT2_EXTENT_UP, &extent);
+ if (pctx->errcode) {
+ printf("Error1: %s on inode %lld\n",
+ error_message(pctx->errcode), pctx->ino);
+ abort();
+ }
+ goto next;
+ }
+
+ for (blk = extent.e_pblk, blockcnt = extent.e_lblk, i = 0;
+ i < extent.e_len;
+ blk++, blockcnt++, i++) {
+ mark_block_used(ctx, blk);
+
+ if (is_dir) {
+ pctx->errcode = ext2fs_add_dir_block(ctx->fs->dblist, pctx->ino, blk, blockcnt);
+ if (pctx->errcode) {
+ pctx->blk = blk;
+ pctx->num = blockcnt;
+ fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
+ /* Should never get here */
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
+ }
+ }
+ }
+ pb->num_blocks += extent.e_len;
+ pb->last_block = extent.e_lblk + extent.e_len - 1;
+ next:
+ pctx->errcode = ext2fs_extent_get(ehandle,
+ EXT2_EXTENT_NEXT_SIB,
+ &extent);
+ }
+ if (pctx->errcode == EXT2_ET_EXTENT_NO_NEXT)
+ pctx->errcode = 0;
+}
+
+static void check_blocks_extents(e2fsck_t ctx, struct problem_context *pctx,
+ struct process_block_struct *pb,
+ char *block_buf)
+{
+ struct ext2_inode *inode = pctx->inode;
+ ext2_extent_handle_t ehandle;
+ ext2_filsys fs = ctx->fs;
+ ext2_ino_t ino = pctx->ino;
+
+ pctx->errcode = ext2fs_extent_open(fs, ino, &ehandle);
+ if (pctx->errcode &&
+ fix_problem(ctx, PR_1_READ_EXTENT, pctx)) {
+ e2fsck_clear_inode(ctx, ino, inode, 0, "check_blocks_extents");
+ pctx->errcode = 0;
+ return;
+ }
+
+ scan_extent_node(ctx, pctx, pb, ehandle);
+
+ ext2fs_extent_free(ehandle);
+}
+
/*
* This subroutine is called on each inode to account for all of the
* blocks used by that inode.
@@ -1512,13 +1772,22 @@
}
}
- if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
+ if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf)) {
+ if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+ goto out;
pb.num_blocks++;
+ }
- if (ext2fs_inode_has_valid_blocks(inode))
- pctx->errcode = ext2fs_block_iterate2(fs, ino,
- pb.is_dir ? BLOCK_FLAG_HOLE : 0,
- block_buf, process_block, &pb);
+ if (ext2fs_inode_has_valid_blocks(inode)) {
+ if ((ctx->fs->super->s_feature_incompat &
+ EXT3_FEATURE_INCOMPAT_EXTENTS) &&
+ (inode->i_flags & EXT4_EXTENTS_FL))
+ check_blocks_extents(ctx, pctx, &pb, block_buf);
+ else
+ pctx->errcode = ext2fs_block_iterate2(fs, ino,
+ pb.is_dir ? BLOCK_FLAG_HOLE : 0,
+ block_buf, process_block, &pb);
+ }
end_problem_latch(ctx, PR_LATCH_BLOCK);
end_problem_latch(ctx, PR_LATCH_TOOBIG);
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
@@ -1530,20 +1799,9 @@
ctx->fs_fragmented++;
if (pb.clear) {
- inode->i_links_count = 0;
- ext2fs_icount_store(ctx->inode_link_info, ino, 0);
- inode->i_dtime = ctx->now;
- dirty_inode++;
- ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
- ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
- ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
- /*
- * The inode was probably partially accounted for
- * before processing was aborted, so we need to
- * restart the pass 1 scan.
- */
- ctx->flags |= E2F_FLAG_RESTART;
- goto out;
+ e2fsck_clear_inode(ctx, ino, inode, E2F_FLAG_RESTART,
+ "check_blocks");
+ return;
}
if (pb.is_dir) {
@@ -1583,15 +1841,9 @@
if (!pb.num_blocks && pb.is_dir) {
if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
- inode->i_links_count = 0;
- ext2fs_icount_store(ctx->inode_link_info, ino, 0);
- inode->i_dtime = ctx->now;
- dirty_inode++;
- ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
- ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
- ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
+ e2fsck_clear_inode(ctx, ino, inode, 0, "check_blocks");
ctx->fs_directory_count--;
- goto out;
+ return;
}
}
diff --git a/e2fsck/pass1b.c b/e2fsck/pass1b.c
index dab3134..06cf87b 100644
--- a/e2fsck/pass1b.c
+++ b/e2fsck/pass1b.c
@@ -294,7 +294,8 @@
if (ext2fs_inode_has_valid_blocks(&inode) ||
(ino == EXT2_BAD_INO))
pctx.errcode = ext2fs_block_iterate2(fs, ino,
- 0, block_buf, process_pass1b_block, &pb);
+ BLOCK_FLAG_READ_ONLY, block_buf,
+ process_pass1b_block, &pb);
if (inode.i_file_acl)
process_pass1b_block(fs, &inode.i_file_acl,
BLOCK_COUNT_EXTATTR, 0, 0, &pb);
@@ -590,20 +591,17 @@
e2fsck_read_inode(ctx, ino, &inode, "delete_file");
if (ext2fs_inode_has_valid_blocks(&inode))
- pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
- delete_file_block, &pb);
+ pctx.errcode = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_READ_ONLY,
+ block_buf, delete_file_block, &pb);
if (pctx.errcode)
fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
- ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
- ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
if (ctx->inode_bad_map)
ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
/* Inode may have changed by block_iterate, so reread it */
e2fsck_read_inode(ctx, ino, &inode, "delete_file");
- inode.i_links_count = 0;
- inode.i_dtime = ctx->now;
+ e2fsck_clear_inode(ctx, ino, &inode, 0, "delete_file");
if (inode.i_file_acl &&
(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
count = 1;
@@ -629,7 +627,6 @@
delete_file_block(fs, &inode.i_file_acl,
BLOCK_COUNT_EXTATTR, 0, 0, &pb);
}
- e2fsck_write_inode(ctx, ino, &inode, "delete_file");
}
struct clone_struct {
diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
index b79461d..906662d 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -102,7 +102,7 @@
int bad_dir;
#ifdef RESOURCE_TRACK
- init_resource_track(&rtrack);
+ init_resource_track(&rtrack, ctx->fs->io);
#endif
clear_problem_context(&cd.pctx);
@@ -151,7 +151,7 @@
cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
&cd);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+ if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART)
return;
if (cd.pctx.errcode) {
fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
@@ -280,7 +280,7 @@
#ifdef RESOURCE_TRACK
if (ctx->options & E2F_OPT_TIME2) {
e2fsck_clear_progbar(ctx);
- print_resource_track(_("Pass 2"), &rtrack);
+ print_resource_track(_("Pass 2"), &rtrack, fs->io);
}
#endif
}
@@ -727,7 +727,7 @@
buf = cd->buf;
ctx = cd->ctx;
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+ if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART)
return DIRENT_ABORT;
if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
@@ -831,6 +831,9 @@
dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
prev = 0;
do {
+ int group;
+ ext2_ino_t first_unused_inode;
+
problem = 0;
dirent = (struct ext2_dir_entry *) (buf + offset);
cd->pctx.dirent = dirent;
@@ -880,12 +883,6 @@
(dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
(dirent->inode > fs->super->s_inodes_count)) {
problem = PR_2_BAD_INO;
- } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
- dirent->inode))) {
- /*
- * If the inode is unused, offer to clear it.
- */
- problem = PR_2_UNUSED_INODE;
} else if (ctx->inode_bb_map &&
(ext2fs_test_inode_bitmap(ctx->inode_bb_map,
dirent->inode))) {
@@ -962,6 +959,67 @@
return DIRENT_ABORT;
}
+ group = ext2fs_group_of_ino(fs, dirent->inode);
+ first_unused_inode = group * fs->super->s_inodes_per_group +
+ 1 + fs->super->s_inodes_per_group -
+ fs->group_desc[group].bg_itable_unused;
+ cd->pctx.group = group;
+
+ /*
+ * Check if the inode was missed out because _INODE_UNINIT
+ * flag was set or bg_itable_unused was incorrect.
+ * If that is the case restart e2fsck.
+ * XXX Optimisations TODO:
+ * 1. only restart e2fsck once
+ * 2. only exposed inodes are checked again.
+ */
+ if (fs->group_desc[group].bg_flags & EXT2_BG_INODE_UNINIT) {
+ if (fix_problem(ctx, PR_2_INOREF_BG_INO_UNINIT,
+ &cd->pctx)){
+ fs->group_desc[group].bg_flags &=
+ ~EXT2_BG_INODE_UNINIT;
+ ctx->flags |= E2F_FLAG_RESTART |
+ E2F_FLAG_SIGNAL_MASK;
+ } else {
+ ext2fs_unmark_valid(fs);
+ if (problem == PR_2_BAD_INO)
+ goto next;
+ }
+ } else if (dirent->inode >= first_unused_inode) {
+ if (fix_problem(ctx, PR_2_INOREF_IN_UNUSED, &cd->pctx)){
+ fs->group_desc[group].bg_itable_unused = 0;
+ fs->group_desc[group].bg_flags &=
+ ~EXT2_BG_INODE_UNINIT;
+ ext2fs_mark_super_dirty(fs);
+ ctx->flags |= E2F_FLAG_RESTART;
+ goto restart_fsck;
+ } else {
+ ext2fs_unmark_valid(fs);
+ if (problem == PR_2_BAD_INO)
+ goto next;
+ }
+ }
+
+ if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
+ dirent->inode))) {
+ /*
+ * If the inode is unused, offer to clear it.
+ */
+ problem = PR_2_UNUSED_INODE;
+ }
+
+ if (problem) {
+ if (fix_problem(ctx, problem, &cd->pctx)) {
+ dirent->inode = 0;
+ dir_modified++;
+ goto next;
+ } else {
+ ext2fs_unmark_valid(fs);
+ if (problem == PR_2_BAD_INO)
+ goto next;
+ }
+ }
+
if (check_name(ctx, dirent, ino, &cd->pctx))
dir_modified++;
@@ -1071,8 +1129,9 @@
dict_free_nodes(&de_dict);
return 0;
abort_free_dict:
- dict_free_nodes(&de_dict);
ctx->flags |= E2F_FLAG_ABORT;
+restart_fsck:
+ dict_free_nodes(&de_dict);
return DIRENT_ABORT;
}
@@ -1109,11 +1168,8 @@
struct problem_context pctx;
__u32 count;
- ext2fs_icount_store(ctx->inode_link_info, ino, 0);
e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
- inode.i_links_count = 0;
- inode.i_dtime = ctx->now;
- e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
+ e2fsck_clear_inode(ctx, ino, &inode, 0, "deallocate_inode");
clear_problem_context(&pctx);
pctx.ino = ino;
@@ -1121,10 +1177,6 @@
* Fix up the bitmaps...
*/
e2fsck_read_bitmaps(ctx);
- ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
- ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
- if (ctx->inode_bad_map)
- ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
if (inode.i_file_acl &&
@@ -1225,7 +1277,7 @@
&& !e2fsck_pass1_check_device_inode(fs, &inode))
problem = PR_2_BAD_SOCKET;
else if (LINUX_S_ISLNK(inode.i_mode)
- && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
+ && !e2fsck_pass1_check_symlink(fs, ino, &inode, buf)) {
problem = PR_2_INVALID_SYMLINK;
}
@@ -1253,10 +1305,6 @@
frag = &inode.osd2.hurd2.h_i_frag;
fsize = &inode.osd2.hurd2.h_i_fsize;
break;
- case EXT2_OS_MASIX:
- frag = &inode.osd2.masix2.m_i_frag;
- fsize = &inode.osd2.masix2.m_i_fsize;
- break;
default:
frag = fsize = 0;
}
diff --git a/e2fsck/pass3.c b/e2fsck/pass3.c
index b9c6edd..867cbf8 100644
--- a/e2fsck/pass3.c
+++ b/e2fsck/pass3.c
@@ -61,7 +61,7 @@
unsigned long maxdirs, count;
#ifdef RESOURCE_TRACK
- init_resource_track(&rtrack);
+ init_resource_track(&rtrack, ctx->fs->io);
#endif
clear_problem_context(&pctx);
@@ -87,7 +87,8 @@
#ifdef RESOURCE_TRACK
if (ctx->options & E2F_OPT_TIME) {
e2fsck_clear_progbar(ctx);
- print_resource_track(_("Peak memory"), &ctx->global_rtrack);
+ print_resource_track(_("Peak memory"), &ctx->global_rtrack,
+ NULL);
}
#endif
@@ -142,7 +143,7 @@
#ifdef RESOURCE_TRACK
if (ctx->options & E2F_OPT_TIME2) {
e2fsck_clear_progbar(ctx);
- print_resource_track(_("Pass 3"), &rtrack);
+ print_resource_track(_("Pass 3"), &rtrack, ctx->fs->io);
}
#endif
}
diff --git a/e2fsck/pass4.c b/e2fsck/pass4.c
index dfb3a37..ebc19a8 100644
--- a/e2fsck/pass4.c
+++ b/e2fsck/pass4.c
@@ -15,6 +15,7 @@
#include "e2fsck.h"
#include "problem.h"
+#include <ext2fs/ext2_ext_attr.h>
/*
* This routine is called when an inode is not connected to the
@@ -23,39 +24,45 @@
* This subroutine returns 1 then the caller shouldn't bother with the
* rest of the pass 4 tests.
*/
-static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
+static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i,
+ struct ext2_inode *inode)
{
ext2_filsys fs = ctx->fs;
- struct ext2_inode inode;
struct problem_context pctx;
+ __u32 eamagic = 0;
+ int extra_size = 0;
- e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
+ if (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE) {
+ e2fsck_read_inode_full(ctx, i, inode,EXT2_INODE_SIZE(fs->super),
+ "pass4: disconnect_inode");
+ extra_size = ((struct ext2_inode_large *)inode)->i_extra_isize;
+ } else {
+ e2fsck_read_inode(ctx, i, inode, "pass4: disconnect_inode");
+ }
clear_problem_context(&pctx);
pctx.ino = i;
- pctx.inode = &inode;
+ pctx.inode = inode;
+ if (EXT2_INODE_SIZE(fs->super) -EXT2_GOOD_OLD_INODE_SIZE -extra_size >0)
+ eamagic = *(__u32 *)(((char *)inode) +EXT2_GOOD_OLD_INODE_SIZE +
+ extra_size);
/*
* Offer to delete any zero-length files that does not have
* blocks. If there is an EA block, it might have useful
* information, so we won't prompt to delete it, but let it be
* reconnected to lost+found.
*/
- if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
- LINUX_S_ISDIR(inode.i_mode))) {
+ if (!inode->i_blocks && eamagic != EXT2_EXT_ATTR_MAGIC &&
+ (LINUX_S_ISREG(inode->i_mode) || LINUX_S_ISDIR(inode->i_mode))) {
if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
- ext2fs_icount_store(ctx->inode_link_info, i, 0);
- inode.i_links_count = 0;
- inode.i_dtime = ctx->now;
- e2fsck_write_inode(ctx, i, &inode,
+ e2fsck_clear_inode(ctx, i, inode, 0,
"disconnect_inode");
/*
* Fix up the bitmaps...
*/
e2fsck_read_bitmaps(ctx);
- ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
- ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
ext2fs_inode_alloc_stats2(fs, i, -1,
- LINUX_S_ISDIR(inode.i_mode));
+ LINUX_S_ISDIR(inode->i_mode));
return 0;
}
}
@@ -83,7 +90,7 @@
{
ext2_filsys fs = ctx->fs;
ext2_ino_t i;
- struct ext2_inode inode;
+ struct ext2_inode *inode;
#ifdef RESOURCE_TRACK
struct resource_track rtrack;
#endif
@@ -93,7 +100,7 @@
int group, maxgroup;
#ifdef RESOURCE_TRACK
- init_resource_track(&rtrack);
+ init_resource_track(&rtrack, ctx->fs->io);
#endif
#ifdef MTRACE
@@ -111,6 +118,9 @@
if ((ctx->progress)(ctx, 4, 0, maxgroup))
return;
+ inode = e2fsck_allocate_memory(ctx, EXT2_INODE_SIZE(fs->super),
+ "scratch inode");
+
/* Protect loop from wrap-around if s_inodes_count maxed */
for (i=1; i <= fs->super->s_inodes_count && i > 0; i++) {
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
@@ -138,26 +148,34 @@
fs->blocksize, "bad_inode buffer");
if (e2fsck_process_bad_inode(ctx, 0, i, buf))
continue;
- if (disconnect_inode(ctx, i))
+ if (disconnect_inode(ctx, i, inode))
continue;
ext2fs_icount_fetch(ctx->inode_link_info, i,
&link_count);
ext2fs_icount_fetch(ctx->inode_count, i,
&link_counted);
}
+ if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i) &&
+ (link_counted > EXT2_LINK_MAX))
+ link_counted = 1;
if (link_counted != link_count) {
- e2fsck_read_inode(ctx, i, &inode, "pass4");
+ e2fsck_read_inode(ctx, i, inode, "pass4");
pctx.ino = i;
- pctx.inode = &inode;
- if (link_count != inode.i_links_count) {
+ pctx.inode = inode;
+ if (link_count != inode->i_links_count) {
pctx.num = link_count;
fix_problem(ctx,
PR_4_INCONSISTENT_COUNT, &pctx);
}
pctx.num = link_counted;
- if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
- inode.i_links_count = link_counted;
- e2fsck_write_inode(ctx, i, &inode, "pass4");
+ /* i_link_count was previously exceeded, but no longer
+ * is, fix this but don't consider it an error */
+ if ((LINUX_S_ISDIR(inode->i_mode) && link_counted > 1 &&
+ (inode->i_flags & EXT2_INDEX_FL) &&
+ link_count == 1 && !(ctx->options & E2F_OPT_NO)) ||
+ (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx))) {
+ inode->i_links_count = link_counted;
+ e2fsck_write_inode(ctx, i, inode, "pass4");
}
}
}
@@ -170,10 +188,12 @@
errout:
if (buf)
ext2fs_free_mem(&buf);
+
+ ext2fs_free_mem(&inode);
#ifdef RESOURCE_TRACK
if (ctx->options & E2F_OPT_TIME2) {
e2fsck_clear_progbar(ctx);
- print_resource_track(_("Pass 4"), &rtrack);
+ print_resource_track(_("Pass 4"), &rtrack, ctx->fs->io);
}
#endif
}
diff --git a/e2fsck/pass5.c b/e2fsck/pass5.c
index 56619c3..b70e8d1 100644
--- a/e2fsck/pass5.c
+++ b/e2fsck/pass5.c
@@ -30,7 +30,7 @@
#endif
#ifdef RESOURCE_TRACK
- init_resource_track(&rtrack);
+ init_resource_track(&rtrack, ctx->fs->io);
#endif
clear_problem_context(&pctx);
@@ -67,7 +67,7 @@
#ifdef RESOURCE_TRACK
if (ctx->options & E2F_OPT_TIME2) {
e2fsck_clear_progbar(ctx);
- print_resource_track(_("Pass 5"), &rtrack);
+ print_resource_track(_("Pass 5"), &rtrack, ctx->fs->io);
}
#endif
}
@@ -114,14 +114,14 @@
blk_t i, super;
int *free_array;
int group = 0;
- unsigned int blocks = 0;
- unsigned int free_blocks = 0;
+ blk_t blocks = 0;
+ blk_t free_blocks = 0;
int group_free = 0;
int actual, bitmap;
struct problem_context pctx;
int problem, save_problem, fixit, had_problem;
errcode_t retval;
- int lazy_bg = 0;
+ int lazy_flag, csum_flag;
int skip_group = 0;
clear_problem_context(&pctx);
@@ -158,15 +158,16 @@
goto errout;
}
- if (EXT2_HAS_COMPAT_FEATURE(fs->super, EXT2_FEATURE_COMPAT_LAZY_BG))
- lazy_bg++;
-
+ lazy_flag = EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_LAZY_BG);
+ csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
redo_counts:
had_problem = 0;
save_problem = 0;
pctx.blk = pctx.blk2 = NO_BLK;
- if (lazy_bg && (fs->group_desc[group].bg_flags &
- EXT2_BG_BLOCK_UNINIT))
+ if ((lazy_flag || csum_flag) &&
+ (fs->group_desc[group].bg_flags & EXT2_BG_BLOCK_UNINIT))
skip_group++;
super = fs->super->s_first_data_block;
for (i = fs->super->s_first_data_block;
@@ -206,6 +207,17 @@
* Block used, but not marked in use in the bitmap.
*/
problem = PR_5_BLOCK_USED;
+
+ if (skip_group) {
+ struct problem_context pctx2;
+ pctx2.blk = i;
+ pctx2.group = group;
+ if (fix_problem(ctx, PR_5_BLOCK_UNINIT,&pctx2)){
+ fs->group_desc[group].bg_flags &=
+ ~EXT2_BG_BLOCK_UNINIT;
+ skip_group = 0;
+ }
+ }
}
if (pctx.blk == NO_BLK) {
pctx.blk = pctx.blk2 = i;
@@ -224,7 +236,7 @@
had_problem++;
do_counts:
- if (!bitmap && !skip_group) {
+ if (!bitmap && (!skip_group || csum_flag)) {
group_free++;
free_blocks++;
}
@@ -241,7 +253,7 @@
if ((ctx->progress)(ctx, 5, group,
fs->group_desc_count*2))
goto errout;
- if (lazy_bg &&
+ if ((lazy_flag || csum_flag) &&
(i != fs->super->s_blocks_count-1) &&
(fs->group_desc[group].bg_flags &
EXT2_BG_BLOCK_UNINIT))
@@ -321,7 +333,7 @@
errcode_t retval;
struct problem_context pctx;
int problem, save_problem, fixit, had_problem;
- int lazy_bg = 0;
+ int lazy_flag, csum_flag;
int skip_group = 0;
clear_problem_context(&pctx);
@@ -358,16 +370,16 @@
goto errout;
}
- if (EXT2_HAS_COMPAT_FEATURE(fs->super,
- EXT2_FEATURE_COMPAT_LAZY_BG))
- lazy_bg++;
-
+ lazy_flag = EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_LAZY_BG);
+ csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
redo_counts:
had_problem = 0;
save_problem = 0;
pctx.ino = pctx.ino2 = 0;
- if (lazy_bg && (fs->group_desc[group].bg_flags &
- EXT2_BG_INODE_UNINIT))
+ if ((lazy_flag || csum_flag) &&
+ (fs->group_desc[group].bg_flags & EXT2_BG_INODE_UNINIT))
skip_group++;
/* Protect loop from wrap-around if inodes_count is maxed */
@@ -390,6 +402,21 @@
* Inode used, but not in bitmap
*/
problem = PR_5_INODE_USED;
+
+ /* We should never hit this, because it means that
+ * inodes were marked in use that weren't noticed
+ * in pass1 or pass 2. It is easier to fix the problem
+ * than to kill e2fsck and leave the user stuck. */
+ if (skip_group) {
+ struct problem_context pctx2;
+ pctx2.blk = i;
+ pctx2.group = group;
+ if (fix_problem(ctx, PR_5_INODE_UNINIT,&pctx2)){
+ fs->group_desc[group].bg_flags &=
+ ~EXT2_BG_INODE_UNINIT;
+ skip_group = 0;
+ }
+ }
}
if (pctx.ino == 0) {
pctx.ino = pctx.ino2 = i;
@@ -411,7 +438,7 @@
if (bitmap) {
if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
dirs_count++;
- } else if (!skip_group) {
+ } else if (!skip_group || csum_flag) {
group_free++;
free_inodes++;
}
@@ -430,7 +457,7 @@
group + fs->group_desc_count,
fs->group_desc_count*2))
goto errout;
- if (lazy_bg &&
+ if ((lazy_flag || csum_flag) &&
(i != fs->super->s_inodes_count) &&
(fs->group_desc[group].bg_flags &
EXT2_BG_INODE_UNINIT))
@@ -563,7 +590,7 @@
clear_problem_context(&pctx);
- end = fs->block_map->start +
+ end = ext2fs_get_block_bitmap_start(fs->block_map) +
(EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
&save_blocks_count);
diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index e00dbc1..d9ae911 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -54,7 +54,7 @@
N_("Allocate"), /* 4 */
N_("Expand"), /* 5 */
N_("Connect to /lost+found"), /* 6 */
- N_("Create"), /* 7 */
+ N_("Create"), /* 7 */
N_("Salvage"), /* 8 */
N_("Truncate"), /* 9 */
N_("Clear inode"), /* 10 */
@@ -104,11 +104,11 @@
/* Block bitmap not in group */
{ PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g. (@b %b)\n"),
- PROMPT_RELOCATE, PR_LATCH_RELOC },
+ PROMPT_RELOCATE, PR_LATCH_RELOC },
/* Inode bitmap not in group */
{ PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g. (@b %b)\n"),
- PROMPT_RELOCATE, PR_LATCH_RELOC },
+ PROMPT_RELOCATE, PR_LATCH_RELOC },
/* Inode table not in group */
{ PR_0_ITABLE_NOT_GROUP,
@@ -132,7 +132,7 @@
"Either the @S or the partition table is likely to be corrupt!\n"),
PROMPT_ABORT, 0 },
- /* Fragments not supported */
+ /* Fragments not supported */
{ PR_0_NO_FRAGMENTS,
N_("@S @b_size = %b, fragsize = %c.\n"
"This version of e2fsck does not support fragment sizes different\n"
@@ -148,7 +148,7 @@
{ PR_0_FIRST_DATA_BLOCK,
N_("@S first_data_@b = %b, should have been %c\n"),
PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
-
+
/* Adding UUID to filesystem */
{ PR_0_ADD_UUID,
N_("@f did not have a UUID; generating one.\n\n"),
@@ -169,7 +169,7 @@
PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
/* Error determing physical device size of filesystem */
- { PR_0_GETSIZE_ERROR,
+ { PR_0_GETSIZE_ERROR,
N_("Error determining size of the physical @v: %m\n"),
PROMPT_NONE, PR_FATAL },
@@ -259,12 +259,12 @@
{ PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
N_("@I @b #%B (%b) found in @o @i %i.\n"),
PROMPT_NONE, 0 },
-
+
/* Already cleared block found in orphaned inode */
{ PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
PROMPT_NONE, 0 },
-
+
/* Illegal orphan inode in superblock */
{ PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
N_("@I @o @i %i in @S.\n"),
@@ -351,16 +351,41 @@
N_("Adding dirhash hint to @f.\n\n"),
PROMPT_NONE, 0 },
+ /* group descriptor N checksum is invalid. */
+ { PR_0_GDT_CSUM,
+ N_("@g descriptor %g checksum is invalid. "),
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* group descriptor N marked uninitialized without feature set. */
+ { PR_0_GDT_UNINIT,
+ N_("@g descriptor %g marked uninitialized without feature set.\n"),
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* group N block bitmap uninitialized but inode bitmap in use. */
+ { PR_0_BB_UNINIT_IB_INIT,
+ N_("@g %g @b @B uninitialized but @i @B in use.\n"),
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* Group descriptor N has invalid unused inodes count. */
+ { PR_0_GDT_ITABLE_UNUSED,
+ N_("@g descriptor %g has invalid unused inodes count %b. "),
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* Last group block bitmap uninitialized. */
+ { PR_0_BB_UNINIT_LAST,
+ N_("Last @g @b @B uninitialized. "),
+ PROMPT_FIX, PR_PREEN_OK },
+
/* Pass 1 errors */
-
+
/* Pass 1: Checking inodes, blocks, and sizes */
{ PR_1_PASS_HEADER,
N_("Pass 1: Checking @is, @bs, and sizes\n"),
PROMPT_NONE, 0 },
-
+
/* Root directory is not an inode */
{ PR_1_ROOT_NO_DIR, N_("@r is not a @d. "),
- PROMPT_CLEAR, 0 },
+ PROMPT_CLEAR, 0 },
/* Root directory has dtime set */
{ PR_1_ROOT_DTIME,
@@ -416,7 +441,7 @@
{ PR_1_BAD_I_SIZE,
N_("@i %i, i_size is %Is, @s %N. "),
PROMPT_FIX, PR_PREEN_OK },
-
+
/* Inode has incorrect i_blocks */
{ PR_1_BAD_I_BLOCKS,
N_("@i %i, i_@bs is %Ib, @s %N. "),
@@ -440,7 +465,7 @@
/* Too many bad blocks in inode */
{ PR_1_TOO_MANY_BAD_BLOCKS,
N_("Too many illegal @bs in @i %i.\n"),
- PROMPT_CLEAR_INODE, PR_NO_OK },
+ PROMPT_CLEAR_INODE, PR_NO_OK },
/* Illegal block number in bad block inode */
{ PR_1_BB_ILLEGAL_BLOCK_NUM,
@@ -457,12 +482,12 @@
N_("Duplicate or bad @b in use!\n"),
PROMPT_NONE, 0 },
- /* Bad block used as bad block indirect block */
+ /* Bad block used as bad block indirect block */
{ PR_1_BBINODE_BAD_METABLOCK,
N_("Bad @b %b used as bad @b @i indirect @b. "),
PROMPT_CLEAR, PR_LATCH_BBLOCK },
- /* Inconsistency can't be fixed prompt */
+ /* Inconsistency can't be fixed prompt */
{ PR_1_BBINODE_BAD_METABLOCK_PROMPT,
N_("\nThe bad @b @i has probably been corrupted. You probably\n"
"should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
@@ -470,12 +495,12 @@
PROMPT_CONTINUE, PR_PREEN_NOMSG },
/* Bad primary block */
- { PR_1_BAD_PRIMARY_BLOCK,
+ { PR_1_BAD_PRIMARY_BLOCK,
N_("\nIf the @b is really bad, the @f can not be fixed.\n"),
PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
-
+
/* Bad primary block prompt */
- { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
+ { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
N_("You can remove this @b from the bad @b list and hope\n"
"that the @b is really OK. But there are no guarantees.\n\n"),
PROMPT_CLEAR, PR_PREEN_NOMSG },
@@ -484,25 +509,25 @@
{ PR_1_BAD_PRIMARY_SUPERBLOCK,
N_("The primary @S (%b) is on the bad @b list.\n"),
PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
-
+
/* Bad primary block group descriptors */
{ PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
N_("Block %b in the primary @g descriptors "
"is on the bad @b list\n"),
PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
-
+
/* Bad superblock in group */
{ PR_1_BAD_SUPERBLOCK,
N_("Warning: Group %g's @S (%b) is bad.\n"),
PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
-
+
/* Bad block group descriptors in group */
{ PR_1_BAD_GROUP_DESCRIPTORS,
N_("Warning: Group %g's copy of the @g descriptors has a bad "
"@b (%b).\n"),
PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
- /* Block claimed for no reason */
+ /* Block claimed for no reason */
{ PR_1_PROGERR_CLAIMED_BLOCK,
N_("Programming error? @b #%b claimed for no reason in "
"process_bad_@b.\n"),
@@ -512,27 +537,27 @@
{ PR_1_RELOC_BLOCK_ALLOCATE,
N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
PROMPT_NONE, PR_PREEN_OK },
-
+
/* Error allocating block buffer during relocation process */
{ PR_1_RELOC_MEMORY_ALLOCATE,
N_("@A @b buffer for relocating %s\n"),
PROMPT_NONE, PR_PREEN_OK },
-
- /* Relocating metadata group information from X to Y */
+
+ /* Relocating metadata group information from X to Y */
{ PR_1_RELOC_FROM_TO,
N_("Relocating @g %g's %s from %b to %c...\n"),
PROMPT_NONE, PR_PREEN_OK },
-
+
/* Relocating metatdata group information to X */
{ PR_1_RELOC_TO,
N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
PROMPT_NONE, PR_PREEN_OK },
-
+
/* Block read error during relocation process */
{ PR_1_RELOC_READ_ERR,
N_("Warning: could not read @b %b of %s: %m\n"),
PROMPT_NONE, PR_PREEN_OK },
-
+
/* Block write error during relocation process */
{ PR_1_RELOC_WRITE_ERR,
N_("Warning: could not write @b %b for %s: %m\n"),
@@ -568,25 +593,25 @@
N_("Error while iterating over @bs in @i %i: %m\n"),
PROMPT_NONE, PR_FATAL },
- /* Error while storing inode count information */
+ /* Error while storing inode count information */
{ PR_1_ICOUNT_STORE,
N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
PROMPT_NONE, PR_FATAL },
- /* Error while storing directory block information */
+ /* Error while storing directory block information */
{ PR_1_ADD_DBLOCK,
N_("Error storing @d @b information "
"(@i=%i, @b=%b, num=%N): %m\n"),
PROMPT_NONE, PR_FATAL },
- /* Error while reading inode (for clearing) */
+ /* Error while reading inode (for clearing) */
{ PR_1_READ_INODE,
N_("Error reading @i %i: %m\n"),
PROMPT_NONE, PR_FATAL },
/* Suppress messages prompt */
{ PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
-
+
/* Imagic flag set on an inode when filesystem doesn't support it */
{ PR_1_SET_IMAGIC,
N_("@i %i has imagic flag set. "),
@@ -613,11 +638,11 @@
N_("@f has feature flag(s) set, but is a revision 0 @f. "),
PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
- /* Journal inode is not in use, but contains data */
+ /* Journal inode is not in use, but contains data */
{ PR_1_JOURNAL_INODE_NOT_CLEAR,
N_("@j @i is not in use, but contains data. "),
- PROMPT_CLEAR, PR_PREEN_OK },
-
+ PROMPT_CLEAR, PR_PREEN_OK },
+
/* Journal has bad mode */
{ PR_1_JOURNAL_BAD_MODE,
N_("@j is not regular file. "),
@@ -626,14 +651,14 @@
/* Deal with inodes that were part of orphan linked list */
{ PR_1_LOW_DTIME,
N_("@i %i was part of the @o @i list. "),
- PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
+ PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
/* Deal with inodes that were part of corrupted orphan linked
list (latch question) */
{ PR_1_ORPHAN_LIST_REFUGEES,
N_("@is that were part of a corrupted orphan linked list found. "),
- PROMPT_FIX, 0 },
-
+ PROMPT_FIX, 0 },
+
/* Error allocating refcount structure */
{ PR_1_ALLOCATE_REFCOUNT,
N_("@A refcount structure (%N): %m\n"),
@@ -653,13 +678,13 @@
{ PR_1_EXTATTR_READ_ABORT,
N_("Error reading @a @b %b (%m). "),
PROMPT_ABORT, 0 },
-
+
/* Extended attribute reference count incorrect */
{ PR_1_EXTATTR_REFCOUNT,
N_("@a @b %b has reference count %B, @s %N. "),
PROMPT_FIX, 0 },
-
- /* Error writing Extended Attribute block while fixing refcount */
+
+ /* Error writing Extended Attribute block while fixing refcount */
{ PR_1_EXTATTR_WRITE,
N_("Error writing @a @b %b (%m). "),
PROMPT_ABORT, 0 },
@@ -667,22 +692,22 @@
/* Multiple EA blocks not supported */
{ PR_1_EA_MULTI_BLOCK,
N_("@a @b %b has h_@bs > 1. "),
- PROMPT_CLEAR, 0},
+ PROMPT_CLEAR, 0},
/* Error allocating EA region allocation structure */
{ PR_1_EA_ALLOC_REGION,
N_("@A @a @b %b. "),
PROMPT_ABORT, 0},
-
+
/* Error EA allocation collision */
{ PR_1_EA_ALLOC_COLLISION,
N_("@a @b %b is corrupt (allocation collision). "),
PROMPT_CLEAR, 0},
-
+
/* Bad extended attribute name */
{ PR_1_EA_BAD_NAME,
N_("@a @b %b is corrupt (@n name). "),
- PROMPT_CLEAR, 0},
+ PROMPT_CLEAR, 0},
/* Bad extended attribute value */
{ PR_1_EA_BAD_VALUE,
@@ -694,7 +719,7 @@
N_("@i %i is too big. "), PROMPT_TRUNCATE, 0 },
/* Directory too big */
- { PR_1_TOOBIG_DIR,
+ { PR_1_TOOBIG_DIR,
N_("@b #%B (%b) causes @d to be too big. "),
PROMPT_CLEAR, PR_LATCH_TOOBIG },
@@ -713,31 +738,31 @@
N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
PROMPT_CLEAR_HTREE, PR_PREEN_OK },
- /* INDEX_FL flag set on a non-directory */
+ /* INDEX_FL flag set on a non-directory */
{ PR_1_HTREE_NODIR,
N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
PROMPT_CLEAR_HTREE, PR_PREEN_OK },
- /* Invalid root node in HTREE directory */
+ /* Invalid root node in HTREE directory */
{ PR_1_HTREE_BADROOT,
N_("@h %i has an @n root node.\n"),
PROMPT_CLEAR_HTREE, PR_PREEN_OK },
- /* Unsupported hash version in HTREE directory */
+ /* Unsupported hash version in HTREE directory */
{ PR_1_HTREE_HASHV,
N_("@h %i has an unsupported hash version (%N)\n"),
PROMPT_CLEAR_HTREE, PR_PREEN_OK },
- /* Incompatible flag in HTREE root node */
+ /* Incompatible flag in HTREE root node */
{ PR_1_HTREE_INCOMPAT,
N_("@h %i uses an incompatible htree root node flag.\n"),
PROMPT_CLEAR_HTREE, PR_PREEN_OK },
- /* HTREE too deep */
+ /* HTREE too deep */
{ PR_1_HTREE_DEPTH,
N_("@h %i has a tree depth (%N) which is too big\n"),
PROMPT_CLEAR_HTREE, PR_PREEN_OK },
-
+
/* Bad block has indirect block that conflicts with filesystem block */
{ PR_1_BB_FS_BLOCK,
N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
@@ -749,34 +774,34 @@
N_("Resize @i (re)creation failed: %m."),
PROMPT_ABORT, 0 },
- /* invalid inode->i_extra_isize */
+ /* invalid inode->i_extra_isize */
{ PR_1_EXTRA_ISIZE,
N_("@i %i has a extra size (%IS) which is @n\n"),
PROMPT_FIX, PR_PREEN_OK },
- /* invalid ea entry->e_name_len */
+ /* invalid ea entry->e_name_len */
{ PR_1_ATTR_NAME_LEN,
N_("@a in @i %i has a namelen (%N) which is @n\n"),
PROMPT_CLEAR, PR_PREEN_OK },
- /* invalid ea entry->e_value_size */
+ /* invalid ea entry->e_value_size */
{ PR_1_ATTR_VALUE_SIZE,
N_("@a in @i %i has a value size (%N) which is @n\n"),
PROMPT_CLEAR, PR_PREEN_OK },
- /* invalid ea entry->e_value_offs */
+ /* invalid ea entry->e_value_offs */
{ PR_1_ATTR_VALUE_OFFSET,
N_("@a in @i %i has a value offset (%N) which is @n\n"),
PROMPT_CLEAR, PR_PREEN_OK },
- /* invalid ea entry->e_value_block */
+ /* invalid ea entry->e_value_block */
{ PR_1_ATTR_VALUE_BLOCK,
N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
PROMPT_CLEAR, PR_PREEN_OK },
- /* invalid ea entry->e_hash */
+ /* invalid ea entry->e_hash */
{ PR_1_ATTR_HASH,
- N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
+ N_("@a in @i %i has a hash (%N) which is @n\n"),
PROMPT_CLEAR, PR_PREEN_OK },
/* inode appears to be a directory */
@@ -784,6 +809,46 @@
N_("@i %i is a %It but it looks like it is really a directory.\n"),
PROMPT_FIX, 0 },
+ /* Error while reading extent tree */
+ { PR_1_READ_EXTENT,
+ N_("Error while reading over @x tree in @i %i: %m\n"),
+ PROMPT_CLEAR_INODE, 0 },
+
+ /* Error deleting a bogus extent */
+ { PR_1_EXTENT_DELETE_FAIL,
+ N_("Error while deleting extent: %m\n"),
+ PROMPT_ABORT, 0 },
+
+ /* Bad starting block in extent */
+ { PR_1_EXTENT_BAD_START_BLK,
+ N_("@i %i has an @n extent\n\t(logical @b %c, @n physical @b %b, len %N)\n"),
+ PROMPT_CLEAR, 0 },
+
+ /* Extent ends beyond filesystem */
+ { PR_1_EXTENT_ENDS_BEYOND,
+ N_("@i %i has an @n extent\n\t(logical @b %c, physical @b %b, @n len %N)\n"),
+ PROMPT_CLEAR, 0 },
+
+ /* EXTENTS_FL flag set on a non-extents filesystem */
+ { PR_1_EXTENTS_SET,
+ N_("@i %i has EXTENTS_FL flag set on @f without extents support.\n"),
+ PROMPT_CLEAR, 0 },
+
+ /* inode has extents, superblock missing INCOMPAT_EXTENTS feature */
+ { PR_1_EXTENT_FEATURE,
+ N_("@i %i is in extent format, but @S is missing EXTENTS feature\n"),
+ PROMPT_FIX, 0 },
+
+ /* inode missing EXTENTS_FL, but is an extent inode */
+ { PR_1_UNSET_EXTENT_FL,
+ N_("@i %i missing EXTENT_FL, but is in extents format\n"),
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* Fast symlink has EXTENTS_FL set */
+ { PR_1_FAST_SYMLINK_EXTENT_FL,
+ N_("Fast symlink %i has EXTENT_FL set. "),
+ PROMPT_CLEAR, 0 },
+
/* Pass 1b errors */
/* Pass 1B: Rescan for duplicate/bad blocks */
@@ -793,12 +858,12 @@
PROMPT_NONE, 0 },
/* Duplicate/bad block(s) header */
- { PR_1B_DUP_BLOCK_HEADER,
+ { PR_1B_DUP_BLOCK_HEADER,
N_("@m @b(s) in @i %i:"),
PROMPT_NONE, 0 },
/* Duplicate/bad block(s) in inode */
- { PR_1B_DUP_BLOCK,
+ { PR_1B_DUP_BLOCK,
" %b",
PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
@@ -806,7 +871,7 @@
{ PR_1B_DUP_BLOCK_END,
"\n",
PROMPT_NONE, PR_PREEN_NOHDR },
-
+
/* Error while scanning inodes */
{ PR_1B_ISCAN_ERROR,
N_("Error while scanning inodes (%i): %m\n"),
@@ -833,29 +898,29 @@
N_("Pass 1C: Scanning directories for @is with @m @bs\n"),
PROMPT_NONE, 0 },
-
+
/* Pass 1D: Reconciling multiply-claimed blocks */
{ PR_1D_PASS_HEADER,
N_("Pass 1D: Reconciling @m @bs\n"),
PROMPT_NONE, 0 },
-
+
/* File has duplicate blocks */
{ PR_1D_DUP_FILE,
N_("File %Q (@i #%i, mod time %IM) \n"
" has %B @m @b(s), shared with %N file(s):\n"),
PROMPT_NONE, 0 },
-
- /* List of files sharing duplicate blocks */
+
+ /* List of files sharing duplicate blocks */
{ PR_1D_DUP_FILE_LIST,
N_("\t%Q (@i #%i, mod time %IM)\n"),
PROMPT_NONE, 0 },
-
- /* File sharing blocks with filesystem metadata */
+
+ /* File sharing blocks with filesystem metadata */
{ PR_1D_SHARE_METADATA,
N_("\t<@f metadata>\n"),
PROMPT_NONE, 0 },
- /* Report of how many duplicate/bad inodes */
+ /* Report of how many duplicate/bad inodes */
{ PR_1D_NUM_DUP_INODES,
N_("(There are %N @is containing @m @bs.)\n\n"),
PROMPT_NONE, 0 },
@@ -868,7 +933,7 @@
/* Clone duplicate/bad blocks? */
{ PR_1D_CLONE_QUESTION,
"", PROMPT_CLONE, PR_NO_OK },
-
+
/* Delete file? */
{ PR_1D_DELETE_QUESTION,
"", PROMPT_DELETE, 0 },
@@ -883,24 +948,24 @@
{ PR_2_PASS_HEADER,
N_("Pass 2: Checking @d structure\n"),
PROMPT_NONE, 0 },
-
+
/* Bad inode number for '.' */
{ PR_2_BAD_INODE_DOT,
N_("@n @i number for '.' in @d @i %i.\n"),
PROMPT_FIX, 0 },
/* Directory entry has bad inode number */
- { PR_2_BAD_INO,
+ { PR_2_BAD_INO,
N_("@E has @n @i #: %Di.\n"),
PROMPT_CLEAR, 0 },
/* Directory entry has deleted or unused inode */
- { PR_2_UNUSED_INODE,
+ { PR_2_UNUSED_INODE,
N_("@E has @D/unused @i %Di. "),
PROMPT_CLEAR, PR_PREEN_OK },
/* Directry entry is link to '.' */
- { PR_2_LINK_DOT,
+ { PR_2_LINK_DOT,
N_("@E @L to '.' "),
PROMPT_CLEAR, 0 },
@@ -910,26 +975,26 @@
PROMPT_CLEAR, 0 },
/* Directory entry contains a link to a directory */
- { PR_2_LINK_DIR,
+ { PR_2_LINK_DIR,
N_("@E @L to @d %P (%Di).\n"),
PROMPT_CLEAR, 0 },
/* Directory entry contains a link to the root directry */
- { PR_2_LINK_ROOT,
+ { PR_2_LINK_ROOT,
N_("@E @L to the @r.\n"),
PROMPT_CLEAR, 0 },
/* Directory entry has illegal characters in its name */
- { PR_2_BAD_NAME,
+ { PR_2_BAD_NAME,
N_("@E has illegal characters in its name.\n"),
PROMPT_FIX, 0 },
- /* Missing '.' in directory inode */
+ /* Missing '.' in directory inode */
{ PR_2_MISSING_DOT,
N_("Missing '.' in @d @i %i.\n"),
PROMPT_FIX, 0 },
- /* Missing '..' in directory inode */
+ /* Missing '..' in directory inode */
{ PR_2_MISSING_DOT_DOT,
N_("Missing '..' in @d @i %i.\n"),
PROMPT_FIX, 0 },
@@ -943,7 +1008,7 @@
{ PR_2_2ND_NOT_DOT_DOT,
N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
PROMPT_FIX, 0 },
-
+
/* i_faddr should be zero */
{ PR_2_FADDR_ZERO,
N_("i_faddr @F %IF, @s zero.\n"),
@@ -975,17 +1040,17 @@
PROMPT_CLEAR, 0 },
/* directory corrupted */
- { PR_2_DIR_CORRUPTED,
+ { PR_2_DIR_CORRUPTED,
N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
PROMPT_SALVAGE, 0 },
-
+
/* filename too long */
- { PR_2_FILENAME_LONG,
+ { PR_2_FILENAME_LONG,
N_("@d @i %i, @b %B, offset %N: filename too long\n"),
PROMPT_TRUNCATE, 0 },
/* Directory inode has a missing block (hole) */
- { PR_2_DIRECTORY_HOLE,
+ { PR_2_DIRECTORY_HOLE,
N_("@d @i %i has an unallocated @b #%B. "),
PROMPT_ALLOCATE, 0 },
@@ -1012,7 +1077,7 @@
/* Duplicate '.' entry */
{ PR_2_DUP_DOT,
N_("@E is duplicate '.' @e.\n"),
- PROMPT_FIX, 0 },
+ PROMPT_FIX, 0 },
/* Duplicate '..' entry */
{ PR_2_DUP_DOT_DOT,
@@ -1028,7 +1093,7 @@
{ PR_2_FINAL_RECLEN,
N_("@E has rec_len of %Dr, @s %N.\n"),
PROMPT_FIX, 0 },
-
+
/* Error allocating icount structure */
{ PR_2_ALLOCATE_ICOUNT,
N_("@A icount structure: %m\n"),
@@ -1108,7 +1173,7 @@
{ PR_2_FEATURE_LARGE_FILES,
N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
PROMPT_FIX, 0 },
-
+
/* Node in HTREE directory not referenced */
{ PR_2_HTREE_NOTREF,
N_("@p @h %d: node (%B) not referenced\n"),
@@ -1132,7 +1197,7 @@
/* Clear invalid HTREE directory */
{ PR_2_HTREE_CLEAR,
N_("@n @h %d (%q). "), PROMPT_CLEAR_HTREE, 0 },
-
+
/* Bad block in htree interior node */
{ PR_2_HTREE_BADBLK,
N_("@p @h %d (%q): bad @b number %b.\n"),
@@ -1167,22 +1232,22 @@
{ PR_2_HTREE_BAD_DEPTH,
N_("@p @h %d: node (%B) has @n depth\n"),
PROMPT_NONE, 0 },
-
+
/* Duplicate directory entry found */
{ PR_2_DUPLICATE_DIRENT,
N_("Duplicate @E found. "),
PROMPT_CLEAR, 0 },
-
+
/* Non-unique filename found */
{ PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
N_("@E has a non-unique filename.\nRename to %s"),
PROMPT_NULL, 0 },
-
+
/* Duplicate directory entry found */
{ PR_2_REPORT_DUP_DIRENT,
N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
PROMPT_NONE, 0 },
-
+
/* i_blocks_hi should be zero */
{ PR_2_BLOCKS_HI_ZERO,
N_("i_blocks_hi @F %N, @s zero.\n"),
@@ -1191,19 +1256,29 @@
/* Unexpected HTREE block */
{ PR_2_UNEXPECTED_HTREE_BLOCK,
N_("Unexpected @b in @h %d (%q).\n"), PROMPT_CLEAR_HTREE, 0 },
-
+
+ /* Inode found in group where _INODE_UNINIT is set */
+ { PR_2_INOREF_BG_INO_UNINIT,
+ N_("@i %i found in @g %g where _INODE_UNINIT is set. "),
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* Inode found in group unused inodes area */
+ { PR_2_INOREF_IN_UNUSED,
+ N_("@i %i found in @g %g unused inodes area. "),
+ PROMPT_FIX, PR_PREEN_OK },
+
/* Pass 3 errors */
/* Pass 3: Checking directory connectivity */
{ PR_3_PASS_HEADER,
N_("Pass 3: Checking @d connectivity\n"),
PROMPT_NONE, 0 },
-
+
/* Root inode not allocated */
{ PR_3_NO_ROOT_INODE,
N_("@r not allocated. "),
- PROMPT_ALLOCATE, 0 },
-
+ PROMPT_ALLOCATE, 0 },
+
/* No room in lost+found */
{ PR_3_EXPAND_LF_DIR,
N_("No room in @l @d. "),
@@ -1245,20 +1320,20 @@
PROMPT_NONE, 0 },
/* Error in ext2fs_new_block while creating /lost+found */
- { PR_3_ERR_LPF_NEW_BLOCK,
+ { PR_3_ERR_LPF_NEW_BLOCK,
N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
PROMPT_NONE, 0 },
-
+
/* Error in ext2fs_new_inode while creating /lost+found */
{ PR_3_ERR_LPF_NEW_INODE,
N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
PROMPT_NONE, 0 },
- /* Error in ext2fs_new_dir_block while creating /lost+found */
+ /* Error in ext2fs_new_dir_block while creating /lost+found */
{ PR_3_ERR_LPF_NEW_DIR_BLOCK,
N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
PROMPT_NONE, 0 },
-
+
/* Error while writing directory block for /lost+found */
{ PR_3_ERR_LPF_WRITE_BLOCK,
N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
@@ -1274,7 +1349,7 @@
N_("Couldn't fix parent of @i %i: %m\n\n"),
PROMPT_NONE, 0 },
- /* Couldn't fix parent directory -- couldn't find it */
+ /* Couldn't fix parent directory -- couldn't find it */
{ PR_3_FIX_PARENT_NOFIND,
N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
PROMPT_NONE, 0 },
@@ -1287,22 +1362,22 @@
/* Error creating root directory */
{ PR_3_CREATE_ROOT_ERROR,
N_("Error creating root @d (%s): %m\n"),
- PROMPT_NONE, PR_FATAL },
+ PROMPT_NONE, PR_FATAL },
/* Error creating lost and found directory */
{ PR_3_CREATE_LPF_ERROR,
N_("Error creating /@l @d (%s): %m\n"),
- PROMPT_NONE, PR_FATAL },
+ PROMPT_NONE, PR_FATAL },
/* Root inode is not directory; aborting */
{ PR_3_ROOT_NOT_DIR_ABORT,
N_("@r is not a @d; aborting.\n"),
- PROMPT_NONE, PR_FATAL },
+ PROMPT_NONE, PR_FATAL },
/* Cannot proceed without a root inode. */
{ PR_3_NO_ROOT_INODE_ABORT,
N_("Cannot proceed without a @r.\n"),
- PROMPT_NONE, PR_FATAL },
+ PROMPT_NONE, PR_FATAL },
/* Internal error: couldn't find dir_info */
{ PR_3_NO_DIRINFO,
@@ -1340,19 +1415,19 @@
{ PR_3A_OPTIMIZE_DIR,
" %d",
PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
-
- /* Rehashing dir end */
+
+ /* Rehashing dir end */
{ PR_3A_OPTIMIZE_DIR_END,
"\n",
PROMPT_NONE, PR_PREEN_NOHDR },
/* Pass 4 errors */
-
+
/* Pass 4: Checking reference counts */
{ PR_4_PASS_HEADER,
N_("Pass 4: Checking reference counts\n"),
PROMPT_NONE, 0 },
-
+
/* Unattached zero-length inode */
{ PR_4_ZERO_LEN_INODE,
N_("@u @z @i %i. "),
@@ -1376,22 +1451,22 @@
PROMPT_NONE, 0 },
/* Pass 5 errors */
-
+
/* Pass 5: Checking group summary information */
{ PR_5_PASS_HEADER,
N_("Pass 5: Checking @g summary information\n"),
PROMPT_NONE, 0 },
-
+
/* Padding at end of inode bitmap is not set. */
{ PR_5_INODE_BMAP_PADDING,
N_("Padding at end of @i @B is not set. "),
PROMPT_FIX, PR_PREEN_OK },
-
+
/* Padding at end of block bitmap is not set. */
{ PR_5_BLOCK_BMAP_PADDING,
N_("Padding at end of @b @B is not set. "),
PROMPT_FIX, PR_PREEN_OK },
-
+
/* Block bitmap differences header */
{ PR_5_BLOCK_BITMAP_HEADER,
N_("@b @B differences: "),
@@ -1401,13 +1476,13 @@
{ PR_5_BLOCK_UNUSED,
" -%b",
PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
+
/* Block used, but not marked used in bitmap */
{ PR_5_BLOCK_USED,
" +%b",
PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
- /* Block bitmap differences end */
+ /* Block bitmap differences end */
{ PR_5_BLOCK_BITMAP_END,
"\n",
PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
@@ -1421,13 +1496,13 @@
{ PR_5_INODE_UNUSED,
" -%i",
PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
+
/* Inode used, but not marked used in bitmap */
{ PR_5_INODE_USED,
" +%i",
PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
- /* Inode bitmap differences end */
+ /* Inode bitmap differences end */
{ PR_5_INODE_BITMAP_END,
"\n",
PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
@@ -1466,7 +1541,7 @@
/* Internal error: fudging end of bitmap */
{ PR_5_FUDGE_BITMAP_ERROR,
N_("Internal error: fudging end of bitmap (%N)\n"),
- PROMPT_NONE, PR_FATAL },
+ PROMPT_NONE, PR_FATAL },
/* Error copying in replacement inode bitmap */
{ PR_5_COPY_IBITMAP_ERROR,
@@ -1477,12 +1552,12 @@
{ PR_5_COPY_BBITMAP_ERROR,
N_("Error copying in replacement @b @B: %m\n"),
PROMPT_NONE, PR_FATAL },
-
+
/* Block range not used, but marked in bitmap */
{ PR_5_BLOCK_RANGE_UNUSED,
" -(%b--%c)",
PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
+
/* Block range used, but not marked used in bitmap */
{ PR_5_BLOCK_RANGE_USED,
" +(%b--%c)",
@@ -1492,7 +1567,7 @@
{ PR_5_INODE_RANGE_UNUSED,
" -(%i--%j)",
PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
-
+
/* Inode range used, but not marked used in bitmap */
{ PR_5_INODE_RANGE_USED,
" +(%i--%j)",
@@ -1503,6 +1578,16 @@
N_("Recreate journal to make the filesystem ext3 again?\n"),
PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
+ /* Group N block(s) in use but group is marked BLOCK_UNINIT */
+ { PR_5_BLOCK_UNINIT,
+ N_("@g %g @b(s) in use but @g is marked BLOCK_UNINIT\n"),
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* Group N inode(s) in use but group is marked INODE_UNINIT */
+ { PR_5_INODE_UNINIT,
+ N_("@g %g @i(s) in use but @g is marked INODE_UNINIT\n"),
+ PROMPT_FIX, PR_PREEN_OK },
+
{ 0 }
};
@@ -1552,7 +1637,7 @@
struct latch_descr *ldesc;
struct problem_context pctx;
int answer = -1;
-
+
ldesc = find_latch(mask);
if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
clear_problem_context(&pctx);
@@ -1592,7 +1677,7 @@
ctx->group = -1;
}
-static void reconfigure_bool(e2fsck_t ctx, struct e2fsck_problem *ptr,
+static void reconfigure_bool(e2fsck_t ctx, struct e2fsck_problem *ptr,
const char *key, int mask, const char *name)
{
int bool;
@@ -1709,11 +1794,11 @@
answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
if (!answer && !(ptr->flags & PR_NO_OK))
ext2fs_unmark_valid(fs);
-
+
if (print_answer)
printf("%s.\n", answer ?
_(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
-
+
}
if ((ptr->prompt == PROMPT_ABORT) && answer)
diff --git a/e2fsck/problem.h b/e2fsck/problem.h
index 91a6148..ab5c4df 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -16,7 +16,7 @@
ext2_ino_t ino, ino2, dir;
struct ext2_inode *inode;
struct ext2_dir_entry *dirent;
- blk_t blk, blk2;
+ blk64_t blk, blk2;
e2_blkcnt_t blkcount;
int group;
__u64 num;
@@ -82,12 +82,12 @@
/* Adding UUID to filesystem */
#define PR_0_ADD_UUID 0x000009
-/* Relocate hint */
+/* Relocate hint */
#define PR_0_RELOCATE_HINT 0x00000A
/* Miscellaneous superblock corruption */
#define PR_0_MISC_CORRUPT_SUPER 0x00000B
-
+
/* Error determing physical device size of filesystem */
#define PR_0_GETSIZE_ERROR 0x00000C
@@ -135,13 +135,13 @@
/* Clearing orphan inode */
#define PR_0_ORPHAN_CLEAR_INODE 0x000020
-
+
/* Illegal block found in orphaned inode */
#define PR_0_ORPHAN_ILLEGAL_BLOCK_NUM 0x000021
/* Already cleared block found in orphaned inode */
#define PR_0_ORPHAN_ALREADY_CLEARED_BLOCK 0x000022
-
+
/* Illegal orphan inode in superblock */
#define PR_0_ORPHAN_ILLEGAL_HEAD_INODE 0x000023
@@ -196,6 +196,21 @@
/* Superblock hint for external journal incorrect */
#define PR_0_DIRHASH_HINT 0x000034
+/* Group descriptor N checksum is invalid */
+#define PR_0_GDT_CSUM 0x000035
+
+/* Group descriptor N marked uninitialized without feature set. */
+#define PR_0_GDT_UNINIT 0x000036
+
+/* Block bitmap is not initialised and Inode bitmap is */
+#define PR_0_BB_UNINIT_IB_INIT 0x000037
+
+/* Group descriptor N has invalid unused inodes count. */
+#define PR_0_GDT_ITABLE_UNUSED 0x000038
+
+/* Last group block bitmap is uninitialized. */
+#define PR_0_BB_UNINIT_LAST 0x000039
+
/*
* Pass 1 errors
*/
@@ -253,7 +268,7 @@
/* Too many bad blocks in inode */
#define PR_1_TOO_MANY_BAD_BLOCKS 0x010011
-
+
/* Illegal block number in bad block inode */
#define PR_1_BB_ILLEGAL_BLOCK_NUM 0x010012
@@ -262,16 +277,16 @@
/* Duplicate or bad blocks in use! */
#define PR_1_DUP_BLOCKS_PREENSTOP 0x010014
-
-/* Bad block used as bad block indirect block */
+
+/* Bad block used as bad block indirect block */
#define PR_1_BBINODE_BAD_METABLOCK 0x010015
/* Inconsistency can't be fixed prompt */
#define PR_1_BBINODE_BAD_METABLOCK_PROMPT 0x010016
-
+
/* Bad primary block */
#define PR_1_BAD_PRIMARY_BLOCK 0x010017
-
+
/* Bad primary block prompt */
#define PR_1_BAD_PRIMARY_BLOCK_PROMPT 0x010018
@@ -287,24 +302,24 @@
/* Bad block group descriptors in group */
#define PR_1_BAD_GROUP_DESCRIPTORS 0x01001C
-/* Block claimed for no reason */
+/* Block claimed for no reason */
#define PR_1_PROGERR_CLAIMED_BLOCK 0x01001D
/* Error allocating blocks for relocating metadata */
#define PR_1_RELOC_BLOCK_ALLOCATE 0x01001E
-
+
/* Error allocating block buffer during relocation process */
#define PR_1_RELOC_MEMORY_ALLOCATE 0x01001F
-
-/* Relocating metadata group information from X to Y */
+
+/* Relocating metadata group information from X to Y */
#define PR_1_RELOC_FROM_TO 0x010020
-
+
/* Relocating metatdata group information to X */
#define PR_1_RELOC_TO 0x010021
-
+
/* Block read error during relocation process */
#define PR_1_RELOC_READ_ERR 0x010022
-
+
/* Block write error during relocation process */
#define PR_1_RELOC_WRITE_ERR 0x010023
@@ -316,7 +331,7 @@
/* Error allocating icount structure */
#define PR_1_ALLOCATE_ICOUNT 0x010026
-
+
/* Error allocating dbcount */
#define PR_1_ALLOCATE_DBCOUNT 0x010027
@@ -326,10 +341,10 @@
/* Error while iterating over blocks */
#define PR_1_BLOCK_ITERATE 0x010029
-/* Error while storing inode count information */
+/* Error while storing inode count information */
#define PR_1_ICOUNT_STORE 0x01002A
-/* Error while storing directory block information */
+/* Error while storing directory block information */
#define PR_1_ADD_DBLOCK 0x01002B
/* Error while reading inode (for clearing) */
@@ -367,7 +382,7 @@
/* Error allocating refcount structure */
#define PR_1_ALLOCATE_REFCOUNT 0x010038
-
+
/* Error reading Extended Attribute block */
#define PR_1_READ_EA_BLOCK 0x010039
@@ -380,7 +395,7 @@
/* Extended attribute reference count incorrect */
#define PR_1_EXTATTR_REFCOUNT 0x01003C
-/* Error writing Extended Attribute block while fixing refcount */
+/* Error writing Extended Attribute block while fixing refcount */
#define PR_1_EXTATTR_WRITE 0x01003D
/* Multiple EA blocks not supported */
@@ -413,19 +428,19 @@
/* INDEX_FL flag set on a non-HTREE filesystem */
#define PR_1_HTREE_SET 0x010047
-/* INDEX_FL flag set on a non-directory */
+/* INDEX_FL flag set on a non-directory */
#define PR_1_HTREE_NODIR 0x010048
-/* Invalid root node in HTREE directory */
+/* Invalid root node in HTREE directory */
#define PR_1_HTREE_BADROOT 0x010049
-/* Unsupported hash version in HTREE directory */
+/* Unsupported hash version in HTREE directory */
#define PR_1_HTREE_HASHV 0x01004A
-/* Incompatible flag in HTREE root node */
+/* Incompatible flag in HTREE root node */
#define PR_1_HTREE_INCOMPAT 0x01004B
-/* HTREE too deep */
+/* HTREE too deep */
#define PR_1_HTREE_DEPTH 0x01004C
/* Bad block has indirect block that conflicts with filesystem block */
@@ -434,7 +449,7 @@
/* Resize inode failed */
#define PR_1_RESIZE_INODE_CREATE 0x01004E
-/* inode->i_size is too long */
+/* inode->i_size is too long */
#define PR_1_EXTRA_ISIZE 0x01004F
/* attribute name is too long */
@@ -455,6 +470,30 @@
/* inode appears to be a directory */
#define PR_1_TREAT_AS_DIRECTORY 0x010055
+/* Error while reading extent tree */
+#define PR_1_READ_EXTENT 0x010056
+
+/* Error deleting a bogus extent */
+#define PR_1_EXTENT_DELETE_FAIL 0x010057
+
+/* Bad starting block in extent */
+#define PR_1_EXTENT_BAD_START_BLK 0x010058
+
+/* Extent ends beyond filesystem */
+#define PR_1_EXTENT_ENDS_BEYOND 0x010059
+
+/* EXTENTS_FL flag set on a non-extents capable filesystem */
+#define PR_1_EXTENTS_SET 0x01005A
+
+/* inode has extents, superblock missing INCOMPAT_EXTENTS feature */
+#define PR_1_EXTENT_FEATURE 0x01005B
+
+/* inode missing EXTENTS_FL, but is an extent inode */
+#define PR_1_UNSET_EXTENT_FL 0x01005C
+
+/* Fast symlink has EXTENTS_FL set */
+#define PR_1_FAST_SYMLINK_EXTENT_FL 0x01005D
+
/*
* Pass 1b errors
*/
@@ -470,7 +509,7 @@
/* Duplicate/bad block(s) end */
#define PR_1B_DUP_BLOCK_END 0x011003
-
+
/* Error while scanning inodes */
#define PR_1B_ISCAN_ERROR 0x011004
@@ -494,13 +533,13 @@
/* File has duplicate blocks */
#define PR_1D_DUP_FILE 0x013001
-/* List of files sharing duplicate blocks */
+/* List of files sharing duplicate blocks */
#define PR_1D_DUP_FILE_LIST 0x013002
-/* File sharing blocks with filesystem metadata */
+/* File sharing blocks with filesystem metadata */
#define PR_1D_SHARE_METADATA 0x013003
-/* Report of how many duplicate/bad inodes */
+/* Report of how many duplicate/bad inodes */
#define PR_1D_NUM_DUP_INODES 0x013004
/* Duplicated blocks already reassigned or cloned. */
@@ -514,7 +553,7 @@
/* Couldn't clone file (error) */
#define PR_1D_CLONE_ERROR 0x013008
-
+
/*
* Pass 2 errors
*/
@@ -546,10 +585,10 @@
/* Directory entry has illegal characters in its name */
#define PR_2_BAD_NAME 0x020008
-/* Missing '.' in directory inode */
+/* Missing '.' in directory inode */
#define PR_2_MISSING_DOT 0x020009
-/* Missing '..' in directory inode */
+/* Missing '..' in directory inode */
#define PR_2_MISSING_DOT_DOT 0x02000A
/* First entry in directory inode doesn't contain '.' */
@@ -572,16 +611,16 @@
/* i_fsize should be zero */
#define PR_2_FSIZE_ZERO 0x020011
-
+
/* inode has bad mode */
#define PR_2_BAD_MODE 0x020012
/* directory corrupted */
#define PR_2_DIR_CORRUPTED 0x020013
-
+
/* filename too long */
#define PR_2_FILENAME_LONG 0x020014
-
+
/* Directory inode has a missing block (hole) */
#define PR_2_DIRECTORY_HOLE 0x020015
@@ -602,7 +641,7 @@
/* Duplicate '..' entry */
#define PR_2_DUP_DOT_DOT 0x02001B
-
+
/* Internal error: couldn't find dir_info */
#define PR_2_NO_DIRINFO 0x02001C
@@ -711,6 +750,12 @@
/* Unexpected HTREE block */
#define PR_2_UNEXPECTED_HTREE_BLOCK 0x020045
+/* Inode found in group where _INODE_UNINIT is set */
+#define PR_2_INOREF_BG_INO_UNINIT 0x020046
+
+/* Inode found in group unused inodes area */
+#define PR_2_INOREF_IN_UNUSED 0x020047
+
/*
* Pass 3 errors
*/
@@ -751,9 +796,9 @@
/* Error in ext2fs_new_inode while creating /lost+found */
#define PR_3_ERR_LPF_NEW_INODE 0x03000B
-/* Error in ext2fs_new_dir_block while creating /lost+found */
+/* Error in ext2fs_new_dir_block while creating /lost+found */
#define PR_3_ERR_LPF_NEW_DIR_BLOCK 0x03000C
-
+
/* Error while writing directory block for /lost+found */
#define PR_3_ERR_LPF_WRITE_BLOCK 0x03000D
@@ -763,12 +808,12 @@
/* Couldn't fix parent directory -- error */
#define PR_3_FIX_PARENT_ERR 0x03000F
-/* Couldn't fix parent directory -- couldn't find it */
+/* Couldn't fix parent directory -- couldn't find it */
#define PR_3_FIX_PARENT_NOFIND 0x030010
-
+
/* Error allocating inode bitmap */
#define PR_3_ALLOCATE_IBITMAP_ERROR 0x030011
-
+
/* Error creating root directory */
#define PR_3_CREATE_ROOT_ERROR 0x030012
@@ -797,15 +842,15 @@
#define PR_3A_OPTIMIZE_ITER 0x031001
/* Error rehash directory */
-#define PR_3A_OPTIMIZE_DIR_ERR 0x031002
+#define PR_3A_OPTIMIZE_DIR_ERR 0x031002
/* Rehashing dir header */
#define PR_3A_OPTIMIZE_DIR_HEADER 0x031003
/* Rehashing directory %d */
#define PR_3A_OPTIMIZE_DIR 0x031004
-
-/* Rehashing dir end */
+
+/* Rehashing dir end */
#define PR_3A_OPTIMIZE_DIR_END 0x031005
/*
@@ -833,7 +878,7 @@
/* Pass 5: Checking group summary information */
#define PR_5_PASS_HEADER 0x050000
-
+
/* Padding at end of inode bitmap is not set. */
#define PR_5_INODE_BMAP_PADDING 0x050001
@@ -845,11 +890,11 @@
/* Block not used, but marked in bitmap */
#define PR_5_BLOCK_UNUSED 0x050004
-
+
/* Block used, but not marked used in bitmap */
#define PR_5_BLOCK_USED 0x050005
-/* Block bitmap differences end */
+/* Block bitmap differences end */
#define PR_5_BLOCK_BITMAP_END 0x050006
/* Inode bitmap differences header */
@@ -857,11 +902,11 @@
/* Inode not used, but marked in bitmap */
#define PR_5_INODE_UNUSED 0x050008
-
+
/* Inode used, but not marked used in bitmap */
#define PR_5_INODE_USED 0x050009
-/* Inode bitmap differences end */
+/* Inode bitmap differences end */
#define PR_5_INODE_BITMAP_END 0x05000A
/* Free inodes count for group wrong */
@@ -893,16 +938,22 @@
/* Block range not used, but marked in bitmap */
#define PR_5_BLOCK_RANGE_UNUSED 0x050014
-
+
/* Block range used, but not marked used in bitmap */
#define PR_5_BLOCK_RANGE_USED 0x050015
/* Inode range not used, but marked in bitmap */
#define PR_5_INODE_RANGE_UNUSED 0x050016
-
+
/* Inode rangeused, but not marked used in bitmap */
#define PR_5_INODE_RANGE_USED 0x050017
+/* Block in use but group is marked BLOCK_UNINIT */
+#define PR_5_BLOCK_UNINIT 0x050018
+
+/* Inode in use but group is marked INODE_UNINIT */
+#define PR_5_INODE_UNINIT 0x050019
+
/*
* Post-Pass 5 errors
*/
@@ -921,6 +972,6 @@
/* message.c */
void print_e2fsck_message(e2fsck_t ctx, const char *msg,
- struct problem_context *pctx, int first,
+ struct problem_context *pctx, int first,
int recurse);
diff --git a/e2fsck/rehash.c b/e2fsck/rehash.c
index 8e25f52..a1f75ef 100644
--- a/e2fsck/rehash.c
+++ b/e2fsck/rehash.c
@@ -789,7 +789,7 @@
int cur, max, all_dirs, dir_index, first = 1;
#ifdef RESOURCE_TRACK
- init_resource_track(&rtrack);
+ init_resource_track(&rtrack, ctx->fs->io);
#endif
all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
@@ -858,7 +858,7 @@
#ifdef RESOURCE_TRACK
if (ctx->options & E2F_OPT_TIME2) {
e2fsck_clear_progbar(ctx);
- print_resource_track("Pass 3A", &rtrack);
+ print_resource_track("Pass 3A", &rtrack, ctx->fs->io);
}
#endif
}
diff --git a/e2fsck/super.c b/e2fsck/super.c
index 954783e..87a0d78 100644
--- a/e2fsck/super.c
+++ b/e2fsck/super.c
@@ -467,7 +467,9 @@
dgrp_t i;
blk_t should_be;
struct problem_context pctx;
- __u32 free_blocks = 0, free_inodes = 0;
+ blk_t free_blocks = 0;
+ ino_t free_inodes = 0;
+ int lazy_flag, csum_flag;
inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
ipg_max = inodes_per_block * (blocks_per_group - 4);
@@ -574,13 +576,21 @@
/*
* Verify the group descriptors....
*/
- first_block = sb->s_first_data_block;
+ first_block = sb->s_first_data_block;
+ last_block = sb->s_blocks_count-1;
+ lazy_flag = EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_LAZY_BG);
+ csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
pctx.group = i;
- first_block = ext2fs_group_first_block(fs, i);
- last_block = ext2fs_group_last_block(fs, i);
+ if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
+ first_block = ext2fs_group_first_block(fs, i);
+ last_block = ext2fs_group_last_block(fs, i);
+ }
if ((gd->bg_block_bitmap < first_block) ||
(gd->bg_block_bitmap > last_block)) {
@@ -621,6 +631,60 @@
(gd->bg_used_dirs_count > sb->s_inodes_per_group))
ext2fs_unmark_valid(fs);
+ should_be = 0;
+ if (!ext2fs_group_desc_csum_verify(fs, i)) {
+ if (fix_problem(ctx, PR_0_GDT_CSUM, &pctx)) {
+ gd->bg_flags &= ~(EXT2_BG_BLOCK_UNINIT |
+ EXT2_BG_INODE_UNINIT);
+ gd->bg_itable_unused = 0;
+ should_be = 1;
+ }
+ ext2fs_unmark_valid(fs);
+ }
+
+ if (!lazy_flag && !csum_flag &&
+ (gd->bg_flags &(EXT2_BG_BLOCK_UNINIT|EXT2_BG_INODE_UNINIT)||
+ gd->bg_itable_unused != 0)){
+ if (fix_problem(ctx, PR_0_GDT_UNINIT, &pctx)) {
+ gd->bg_flags &= ~(EXT2_BG_BLOCK_UNINIT |
+ EXT2_BG_INODE_UNINIT);
+ gd->bg_itable_unused = 0;
+ should_be = 1;
+ }
+ ext2fs_unmark_valid(fs);
+ }
+
+ if (i == fs->group_desc_count - 1 &&
+ gd->bg_flags & EXT2_BG_BLOCK_UNINIT) {
+ if (fix_problem(ctx, PR_0_BB_UNINIT_LAST, &pctx)) {
+ gd->bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
+ should_be = 1;
+ }
+ ext2fs_unmark_valid(fs);
+ }
+
+ if (gd->bg_flags & EXT2_BG_BLOCK_UNINIT &&
+ !(gd->bg_flags & EXT2_BG_INODE_UNINIT)) {
+ if (fix_problem(ctx, PR_0_BB_UNINIT_IB_INIT, &pctx)) {
+ gd->bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
+ should_be = 1;
+ }
+ ext2fs_unmark_valid(fs);
+ }
+
+ if (csum_flag &&
+ (gd->bg_itable_unused > gd->bg_free_inodes_count ||
+ gd->bg_itable_unused > sb->s_inodes_per_group)) {
+ pctx.blk = gd->bg_itable_unused;
+ if (fix_problem(ctx, PR_0_GDT_ITABLE_UNUSED, &pctx)) {
+ gd->bg_itable_unused = 0;
+ should_be = 1;
+ }
+ ext2fs_unmark_valid(fs);
+ }
+
+ if (should_be)
+ ext2fs_group_desc_csum_set(fs, i);
}
/*
@@ -797,7 +861,6 @@
{
ext2_filsys fs = ctx->fs;
ext2_filsys tfs = 0;
- io_manager io_ptr;
errcode_t retval;
dgrp_t g;
blk_t sb;
diff --git a/e2fsck/swapfs.c b/e2fsck/swapfs.c
deleted file mode 100644
index 9df1d11..0000000
--- a/e2fsck/swapfs.c
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * swapfs.c --- byte-swap an ext2 filesystem
- *
- * Copyright 1996, 1997 by Theodore Ts'o
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- *
- */
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <et/com_err.h>
-#include "e2fsck.h"
-
-#ifdef ENABLE_SWAPFS
-
-struct swap_block_struct {
- ext2_ino_t ino;
- int isdir;
- errcode_t errcode;
- char *dir_buf;
- struct ext2_inode *inode;
-};
-
-/*
- * This is a helper function for block_iterate. We mark all of the
- * indirect and direct blocks as changed, so that block_iterate will
- * write them out.
- */
-static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
- void *priv_data)
-{
- errcode_t retval;
-
- struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
-
- if (sb->isdir && (blockcnt >= 0) && *block_nr) {
- retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
- if (retval) {
- sb->errcode = retval;
- return BLOCK_ABORT;
- }
- retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
- if (retval) {
- sb->errcode = retval;
- return BLOCK_ABORT;
- }
- }
- if (blockcnt >= 0) {
- if (blockcnt < EXT2_NDIR_BLOCKS)
- return 0;
- return BLOCK_CHANGED;
- }
- if (blockcnt == BLOCK_COUNT_IND) {
- if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
- return 0;
- return BLOCK_CHANGED;
- }
- if (blockcnt == BLOCK_COUNT_DIND) {
- if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
- return 0;
- return BLOCK_CHANGED;
- }
- if (blockcnt == BLOCK_COUNT_TIND) {
- if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
- return 0;
- return BLOCK_CHANGED;
- }
- return BLOCK_CHANGED;
-}
-
-/*
- * This function is responsible for byte-swapping all of the indirect,
- * block pointers. It is also responsible for byte-swapping directories.
- */
-static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
- struct ext2_inode *inode)
-{
- errcode_t retval;
- struct swap_block_struct sb;
-
- sb.ino = ino;
- sb.inode = inode;
- sb.dir_buf = block_buf + ctx->fs->blocksize*3;
- sb.errcode = 0;
- sb.isdir = 0;
- if (LINUX_S_ISDIR(inode->i_mode))
- sb.isdir = 1;
-
- retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
- swap_block, &sb);
- if (retval) {
- com_err("swap_inode_blocks", retval,
- _("while calling ext2fs_block_iterate"));
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- if (sb.errcode) {
- com_err("swap_inode_blocks", sb.errcode,
- _("while calling iterator function"));
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
-}
-
-static void swap_inodes(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
- dgrp_t group;
- unsigned int i;
- ext2_ino_t ino = 1;
- char *buf = NULL, *block_buf = NULL;
- errcode_t retval;
- struct ext2_inode * inode;
-
- e2fsck_use_inode_shortcuts(ctx, 1);
-
- retval = ext2fs_get_array(fs->blocksize, fs->inode_blocks_per_group,
- &buf);
- if (retval) {
- com_err("swap_inodes", retval,
- _("while allocating inode buffer"));
- ctx->flags |= E2F_FLAG_ABORT;
- goto errout;
- }
- block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
- "block interate buffer");
- for (group = 0; group < fs->group_desc_count; group++) {
- retval = io_channel_read_blk(fs->io,
- fs->group_desc[group].bg_inode_table,
- fs->inode_blocks_per_group, buf);
- if (retval) {
- com_err("swap_inodes", retval,
- _("while reading inode table (group %d)"),
- group);
- ctx->flags |= E2F_FLAG_ABORT;
- goto errout;
- }
- inode = (struct ext2_inode *) buf;
- for (i=0; i < fs->super->s_inodes_per_group;
- i++, ino++, inode++) {
- ctx->stashed_ino = ino;
- ctx->stashed_inode = inode;
-
- if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
- ext2fs_swap_inode(fs, inode, inode, 0);
-
- /*
- * Skip deleted files.
- */
- if (inode->i_links_count == 0)
- continue;
-
- if (LINUX_S_ISDIR(inode->i_mode) ||
- ((inode->i_block[EXT2_IND_BLOCK] ||
- inode->i_block[EXT2_DIND_BLOCK] ||
- inode->i_block[EXT2_TIND_BLOCK]) &&
- ext2fs_inode_has_valid_blocks(inode)))
- swap_inode_blocks(ctx, ino, block_buf, inode);
-
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- goto errout;
-
- if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
- ext2fs_swap_inode(fs, inode, inode, 1);
- }
- retval = io_channel_write_blk(fs->io,
- fs->group_desc[group].bg_inode_table,
- fs->inode_blocks_per_group, buf);
- if (retval) {
- com_err("swap_inodes", retval,
- _("while writing inode table (group %d)"),
- group);
- ctx->flags |= E2F_FLAG_ABORT;
- goto errout;
- }
- }
-errout:
- if (buf)
- ext2fs_free_mem(&buf);
- if (block_buf)
- ext2fs_free_mem(&block_buf);
- e2fsck_use_inode_shortcuts(ctx, 0);
- ext2fs_flush_icache(fs);
-}
-
-#if defined(__powerpc__) && defined(EXT2FS_ENABLE_SWAPFS)
-/*
- * On the PowerPC, the big-endian variant of the ext2 filesystem
- * has its bitmaps stored as 32-bit words with bit 0 as the LSB
- * of each word. Thus a bitmap with only bit 0 set would be, as
- * a string of bytes, 00 00 00 01 00 ...
- * To cope with this, we byte-reverse each word of a bitmap if
- * we have a big-endian filesystem, that is, if we are *not*
- * byte-swapping other word-sized numbers.
- */
-#define EXT2_BIG_ENDIAN_BITMAPS
-#endif
-
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
-static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
-{
- __u32 *p = (__u32 *) bmap->bitmap;
- int n, nbytes = (bmap->end - bmap->start + 7) / 8;
-
- for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
- *p = ext2fs_swab32(*p);
-}
-#endif
-
-
-void swap_filesys(e2fsck_t ctx)
-{
- ext2_filsys fs = ctx->fs;
-#ifdef RESOURCE_TRACK
- struct resource_track rtrack;
-
- init_resource_track(&rtrack);
-#endif
-
- if (!(ctx->options & E2F_OPT_PREEN))
- printf(_("Pass 0: Doing byte-swap of filesystem\n"));
-
-#ifdef MTRACE
- mtrace_print("Byte swap");
-#endif
-
- if (fs->super->s_mnt_count) {
- fprintf(stderr, _("%s: the filesystem must be freshly "
- "checked using fsck\n"
- "and not mounted before trying to "
- "byte-swap it.\n"), ctx->device_name);
- ctx->flags |= E2F_FLAG_ABORT;
- return;
- }
- if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
- EXT2_FLAG_SWAP_BYTES_WRITE);
- fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
- } else {
- fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
- fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
- }
- swap_inodes(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
- fs->flags |= EXT2_FLAG_SWAP_BYTES;
- fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
- EXT2_FLAG_SWAP_BYTES_WRITE);
-
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
- e2fsck_read_bitmaps(ctx);
- ext2fs_swap_bitmap(fs->inode_map);
- ext2fs_swap_bitmap(fs->block_map);
- fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
-#endif
- fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
- ext2fs_flush(fs);
- fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
-
-#ifdef RESOURCE_TRACK
- if (ctx->options & E2F_OPT_TIME2)
- print_resource_track(_("Byte swap"), &rtrack);
-#endif
-}
-
-#endif
diff --git a/e2fsck/unix.c b/e2fsck/unix.c
index d3a8a2b..93af87b 100644
--- a/e2fsck/unix.c
+++ b/e2fsck/unix.c
@@ -52,8 +52,6 @@
#include "../version.h"
/* Command line options */
-static int swapfs;
-static int normalize_swapfs;
static int cflag; /* check disk */
static int show_version_only;
static int verbose;
@@ -71,7 +69,7 @@
static void usage(e2fsck_t ctx)
{
fprintf(stderr,
- _("Usage: %s [-panyrcdfvstDFSV] [-b superblock] [-B blocksize]\n"
+ _("Usage: %s [-panyrcdfvtDFV] [-b superblock] [-B blocksize]\n"
"\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n"
"\t\t[-l|-L bad_blocks_file] [-C fd] [-j external_journal]\n"
"\t\t[-E extended-options] device\n"),
@@ -268,8 +266,7 @@
if (!defer_check_on_battery)
batt = 0;
- if ((ctx->options & E2F_OPT_FORCE) || bad_blocks_file ||
- cflag || swapfs)
+ if ((ctx->options & E2F_OPT_FORCE) || bad_blocks_file || cflag)
return;
lastcheck = fs->super->s_lastcheck;
@@ -561,7 +558,9 @@
"and may take an argument which\n"
"is set off by an equals ('=') sign. "
"Valid extended options are:\n"
- "\tea_ver=<ea_version (1 or 2)>\n\n"), stderr);
+ "\tea_ver=<ea_version (1 or 2)>\n"
+ "\tuninit_groups\n"
+ "\tinit_groups\n\n"), stderr);
exit(1);
}
}
@@ -739,20 +738,6 @@
case 'N':
ctx->device_name = string_copy(ctx, optarg, 0);
break;
-#ifdef ENABLE_SWAPFS
- case 's':
- normalize_swapfs = 1;
- case 'S':
- swapfs = 1;
- break;
-#else
- case 's':
- case 'S':
- fprintf(stderr, _("Byte-swapping filesystems "
- "not compiled in this version "
- "of e2fsck\n"));
- exit(1);
-#endif
case 'k':
keep_bad_blocks++;
break;
@@ -764,8 +749,9 @@
if (optind != argc - 1)
usage(ctx);
if ((ctx->options & E2F_OPT_NO) && !bad_blocks_file &&
- !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
+ !cflag && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
ctx->options |= E2F_OPT_READONLY;
+
ctx->io_options = strchr(argv[optind], '?');
if (ctx->io_options)
*ctx->io_options++ = 0;
@@ -800,15 +786,6 @@
}
close(fd);
}
-#ifdef ENABLE_SWAPFS
- if (swapfs) {
- if (cflag || bad_blocks_file) {
- fprintf(stderr, _("Incompatible options not "
- "allowed when byte-swapping.\n"));
- exit(FSCK_USAGE);
- }
- }
-#endif
if (cflag && bad_blocks_file) {
fprintf(stderr, _("The -c and the -l/-L options may "
"not be both used at the same time.\n"));
@@ -874,7 +851,7 @@
static const char *my_ver_string = E2FSPROGS_VERSION;
static const char *my_ver_date = E2FSPROGS_DATE;
-
+
int main (int argc, char *argv[])
{
errcode_t retval = 0, orig_retval = 0;
@@ -922,7 +899,7 @@
reserve_stdio_fds();
#ifdef RESOURCE_TRACK
- init_resource_track(&ctx->global_rtrack);
+ init_resource_track(&ctx->global_rtrack, NULL);
#endif
if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
@@ -1243,21 +1220,6 @@
read_bad_blocks_file(ctx, 0, !keep_bad_blocks); /* Test disk */
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
fatal_error(ctx, 0);
-#ifdef ENABLE_SWAPFS
- if (normalize_swapfs) {
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ==
- ext2fs_native_flag()) {
- fprintf(stderr, _("%s: Filesystem byte order "
- "already normalized.\n"), ctx->device_name);
- fatal_error(ctx, 0);
- }
- }
- if (swapfs) {
- swap_filesys(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- fatal_error(ctx, 0);
- }
-#endif
/*
* Mark the system as valid, 'til proven otherwise
@@ -1386,17 +1348,27 @@
}
}
+ if (sb->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM &&
+ !(ctx->options & E2F_OPT_READONLY)) {
+ retval = ext2fs_set_gdt_csum(ctx->fs);
+ if (retval) {
+ com_err(ctx->program_name, retval,
+ _("while setting block group checksum info"));
+ fatal_error(ctx, 0);
+ }
+ }
+
e2fsck_write_bitmaps(ctx);
-
+#ifdef RESOURCE_TRACK
+ io_channel_flush(ctx->fs->io);
+ if (ctx->options & E2F_OPT_TIME)
+ print_resource_track(NULL, &ctx->global_rtrack, ctx->fs->io);
+#endif
ext2fs_close(fs);
ctx->fs = NULL;
free(ctx->filesystem_name);
free(ctx->journal_name);
-#ifdef RESOURCE_TRACK
- if (ctx->options & E2F_OPT_TIME)
- print_resource_track(NULL, &ctx->global_rtrack);
-#endif
e2fsck_free_context(ctx);
remove_error_table(&et_ext2_error_table);
remove_error_table(&et_prof_error_table);
diff --git a/e2fsck/util.c b/e2fsck/util.c
index f761ebb..315a575 100644
--- a/e2fsck/util.c
+++ b/e2fsck/util.c
@@ -29,6 +29,10 @@
#include <malloc.h>
#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
#include "e2fsck.h"
extern e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
@@ -276,11 +280,12 @@
}
#ifdef RESOURCE_TRACK
-void init_resource_track(struct resource_track *track)
+void init_resource_track(struct resource_track *track, io_channel channel)
{
#ifdef HAVE_GETRUSAGE
struct rusage r;
#endif
+ io_stats io_start = 0;
track->brk_start = sbrk(0);
gettimeofday(&track->time_start, 0);
@@ -295,6 +300,14 @@
track->user_start.tv_sec = track->user_start.tv_usec = 0;
track->system_start.tv_sec = track->system_start.tv_usec = 0;
#endif
+ track->bytes_read = 0;
+ track->bytes_written = 0;
+ if (channel && channel->manager && channel->manager->get_stats)
+ channel->manager->get_stats(channel, &io_start);
+ if (io_start) {
+ track->bytes_read = io_start->bytes_read;
+ track->bytes_written = io_start->bytes_written;
+ }
}
#ifdef __GNUC__
@@ -310,7 +323,8 @@
((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
}
-void print_resource_track(const char *desc, struct resource_track *track)
+void print_resource_track(const char *desc, struct resource_track *track,
+ io_channel channel)
{
#ifdef HAVE_GETRUSAGE
struct rusage r;
@@ -347,6 +361,26 @@
printf(_("elapsed time: %6.3f\n"),
timeval_subtract(&time_end, &track->time_start));
#endif
+#define mbytes(x) (((x) + 1048575) / 1048576)
+ if (channel && channel->manager && channel->manager->get_stats) {
+ io_stats delta = 0;
+ unsigned long long bytes_read = 0;
+ unsigned long long bytes_written = 0;
+
+ if (desc)
+ printf("%s: ", desc);
+
+ channel->manager->get_stats(channel, &delta);
+ if (delta) {
+ bytes_read = delta->bytes_read - track->bytes_read;
+ bytes_written = delta->bytes_written -
+ track->bytes_written;
+ }
+ printf("I/O read: %lluMB, write: %lluMB, rate: %.2fMB/s\n",
+ mbytes(bytes_read), mbytes(bytes_written),
+ (double)mbytes(bytes_read + bytes_written) /
+ timeval_subtract(&time_end, &track->time_start));
+ }
}
#endif /* RESOURCE_TRACK */
@@ -363,6 +397,20 @@
}
}
+void e2fsck_read_inode_full(e2fsck_t ctx, unsigned long ino,
+ struct ext2_inode *inode, int bufsize,
+ const char *proc)
+{
+ int retval;
+
+ retval = ext2fs_read_inode_full(ctx->fs, ino, inode, bufsize);
+ if (retval) {
+ com_err("ext2fs_read_inode_full", retval,
+ _("while reading inode %ld in %s"), ino, proc);
+ fatal_error(ctx, 0);
+ }
+}
+
extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
struct ext2_inode * inode, int bufsize,
const char *proc)
@@ -451,7 +499,7 @@
if (io_channel_read_blk(io, superblock,
-SUPERBLOCK_SIZE, buf))
continue;
-#ifdef EXT2FS_ENABLE_SWAPFS
+#ifdef WORDS_BIGENDIAN
if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
ext2fs_swap_super(sb);
#endif
@@ -502,3 +550,60 @@
return 0;
}
+
+#define STRIDE_LENGTH 8
+/*
+ * Helper function which zeros out _num_ blocks starting at _blk_. In
+ * case of an error, the details of the error is returned via _ret_blk_
+ * and _ret_count_ if they are non-NULL pointers. Returns 0 on
+ * success, and an error code on an error.
+ *
+ * As a special case, if the first argument is NULL, then it will
+ * attempt to free the static zeroizing buffer. (This is to keep
+ * programs that check for memory leaks happy.)
+ */
+errcode_t e2fsck_zero_blocks(ext2_filsys fs, blk_t blk, int num,
+ blk_t *ret_blk, int *ret_count)
+{
+ int j, count, next_update, next_update_incr;
+ static char *buf;
+ errcode_t retval;
+
+ /* If fs is null, clean up the static buffer and return */
+ if (!fs) {
+ if (buf) {
+ free(buf);
+ buf = 0;
+ }
+ return 0;
+ }
+ /* Allocate the zeroizing buffer if necessary */
+ if (!buf) {
+ buf = malloc(fs->blocksize * STRIDE_LENGTH);
+ if (!buf) {
+ com_err("malloc", ENOMEM,
+ _("while allocating zeroizing buffer"));
+ exit(1);
+ }
+ memset(buf, 0, fs->blocksize * STRIDE_LENGTH);
+ }
+ /* OK, do the write loop */
+ next_update = 0;
+ next_update_incr = num / 100;
+ if (next_update_incr < 1)
+ next_update_incr = 1;
+ for (j = 0; j < num; j += STRIDE_LENGTH, blk += STRIDE_LENGTH) {
+ count = num - j;
+ if (count > STRIDE_LENGTH)
+ count = STRIDE_LENGTH;
+ retval = io_channel_write_blk(fs->io, blk, count, buf);
+ if (retval) {
+ if (ret_count)
+ *ret_count = count;
+ if (ret_blk)
+ *ret_blk = blk;
+ return retval;
+ }
+ }
+ return 0;
+}
diff --git a/ext2ed/doc/ext2ed-design.sgml b/ext2ed/doc/ext2ed-design.sgml
index 3eaca69..ad2df96 100644
--- a/ext2ed/doc/ext2ed-design.sgml
+++ b/ext2ed/doc/ext2ed-design.sgml
@@ -2722,9 +2722,6 @@
struct {
__u32 h_i_translator;
} hurd1;
- struct {
- __u32 m_i_reserved1;
- } masix1;
} osd1; /* OS dependent 1 */
__u32 i_block[EXT2_N_BLOCKS]; /* Pointers to blocks */
__u32 i_version; /* File version (for NFS) */
@@ -2746,12 +2743,6 @@
__u16 h_i_gid_high;
__u32 h_i_author;
} hurd2;
- struct {
- __u8 m_i_frag; /* Fragment number */
- __u8 m_i_fsize; /* Fragment size */
- __u16 m_pad1;
- __u32 m_i_reserved2[2];
- } masix2;
} osd2; /* OS dependent 2 */
};
</ProgramListing>
diff --git a/lib/Makefile.library b/lib/Makefile.library
index cc2c0ff..52f28bb 100644
--- a/lib/Makefile.library
+++ b/lib/Makefile.library
@@ -13,7 +13,7 @@
clean::
@$(RM) -f subdirs
-$(LIBRARY).a: $(OBJS)
+$(LIB)/$(LIBRARY).a $(LIBRARY).a: $(OBJS)
@echo " GEN_LIB $@"
@(if test -r $@; then $(RM) -f $@.bak && $(MV) $@ $@.bak; fi)
@$(ARGEN) $@ $(OBJS)
diff --git a/lib/blkid/blkid.pc.in b/lib/blkid/blkid.pc.in
index 510aa84..ff51782 100644
--- a/lib/blkid/blkid.pc.in
+++ b/lib/blkid/blkid.pc.in
@@ -8,4 +8,5 @@
Version: @E2FSPROGS_VERSION@
Requires: uuid @DEVMAPPER_REQ@
Cflags: -I${includedir}
-Libs: -L${libdir} -lblkid @DEVMAPPER_PC_LIBS@
+Libs: -L${libdir} -lblkid
+Libs.private: @DEVMAPPER_PC_LIBS@
diff --git a/lib/blkid/getsize.c b/lib/blkid/getsize.c
index 04a0cd8..876d682 100644
--- a/lib/blkid/getsize.c
+++ b/lib/blkid/getsize.c
@@ -186,7 +186,7 @@
#ifdef TEST_PROGRAM
int main(int argc, char **argv)
{
- blkid_loff_t bytes;
+ long long bytes;
int fd;
if (argc < 2) {
diff --git a/lib/blkid/probe.c b/lib/blkid/probe.c
index 4a5c7e7..45885c3 100644
--- a/lib/blkid/probe.c
+++ b/lib/blkid/probe.c
@@ -779,6 +779,7 @@
unsigned char *buf)
{
char uuid[40];
+
/* 168 is the offset to the 40 character uuid:
* http://luks.endorphin.org/LUKS-on-disk-format.pdf */
strncpy(uuid, (char *) buf+168, 40);
diff --git a/lib/blkid/test_probe.in b/lib/blkid/test_probe.in
index 02d42bb..ce8c42f 100644
--- a/lib/blkid/test_probe.in
+++ b/lib/blkid/test_probe.in
@@ -8,7 +8,7 @@
done
fi
-mkdir -p tests
+mkdir -p tests/tmp
for i in $TESTS
do
@@ -19,9 +19,9 @@
echo "non-existent"
continue
fi
- bunzip2 < $SRCDIR/tests/$i.img.bz2 > /tmp/test.img.$$
- ./tst_probe /tmp/test.img.$$ > tests/$i.out
- /bin/rm -f /tmp/test.img.$$ tests/$i.ok tests/$i.failed
+ bunzip2 < $SRCDIR/tests/$i.img.bz2 > tests/tmp/test.img.$$
+ ./tst_probe tests/tmp/test.img.$$ > tests/$i.out
+ /bin/rm -f tests/tmp/test.img.$$ tests/$i.ok tests/$i.failed
cmp -s tests/$i.out $SRCDIR/tests/$i.results
if [ $? = 0 ]; then
echo ok
diff --git a/lib/e2p/feature.c b/lib/e2p/feature.c
index e5f3c3d..cf37447 100644
--- a/lib/e2p/feature.c
+++ b/lib/e2p/feature.c
@@ -45,7 +45,7 @@
{ E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_HUGE_FILE,
"huge_file" },
{ E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_GDT_CSUM,
- "gdt_checksum" },
+ "uninit_groups" },
{ E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_DIR_NLINK,
"dir_nlink" },
{ E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE,
@@ -67,6 +67,8 @@
"extent" },
{ E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_64BIT,
"64bit" },
+ { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_FLEX_BG,
+ "flex_bg"},
{ 0, 0, 0 },
};
diff --git a/lib/e2p/fgetflags.c b/lib/e2p/fgetflags.c
index 0aed6c8..372304f 100644
--- a/lib/e2p/fgetflags.c
+++ b/lib/e2p/fgetflags.c
@@ -65,7 +65,7 @@
#if HAVE_EXT2_IOCTLS
int fd, r, f, save_errno = 0;
- if (!stat(name, &buf) &&
+ if (!lstat(name, &buf) &&
!S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
goto notsupp;
}
diff --git a/lib/e2p/fsetflags.c b/lib/e2p/fsetflags.c
index 2f1277f..3a05324 100644
--- a/lib/e2p/fsetflags.c
+++ b/lib/e2p/fsetflags.c
@@ -71,7 +71,7 @@
#if HAVE_EXT2_IOCTLS
int fd, r, f, save_errno = 0;
- if (!stat(name, &buf) &&
+ if (!lstat(name, &buf) &&
!S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
goto notsupp;
}
diff --git a/lib/e2p/iod.c b/lib/e2p/iod.c
index 808d3a3..84c9709 100644
--- a/lib/e2p/iod.c
+++ b/lib/e2p/iod.c
@@ -27,7 +27,7 @@
{
DIR * dir;
struct dirent *de, *dep;
- int max_len = -1, len;
+ int max_len = -1, len, ret = 0;
#if HAVE_PATHCONF && defined(_PC_NAME_MAX)
max_len = pathconf(dir_name, _PC_NAME_MAX);
@@ -64,9 +64,10 @@
len = max_len;
#endif
memcpy(de, dep, len);
- (*func) (dir_name, de, private);
+ if ((*func)(dir_name, de, private))
+ ret++;
}
free(de);
closedir(dir);
- return 0;
+ return ret;
}
diff --git a/lib/et/com_err.texinfo b/lib/et/com_err.texinfo
index def088c..7a00ffe 100644
--- a/lib/et/com_err.texinfo
+++ b/lib/et/com_err.texinfo
@@ -19,11 +19,9 @@
@ifinfo
@dircategory Development
-@format
-START-INFO-DIR-ENTRY
+@direntry
* Com_err: (com_err). A Common Error Description Library for UNIX.
-END-INFO-DIR-ENTRY
-@end format
+@end direntry
@end ifinfo
@iftex
diff --git a/lib/ext2fs/Makefile.in b/lib/ext2fs/Makefile.in
index 199164a..2766493 100644
--- a/lib/ext2fs/Makefile.in
+++ b/lib/ext2fs/Makefile.in
@@ -7,10 +7,12 @@
@MCONFIG@
-@DEBUGFS_CMT@DEBUGFS_LIB_OBJS = bb_compat.o cmp_bitmaps.o fileio.o \
+@DEBUGFS_CMT@DEBUGFS_LIB_OBJS = bb_compat.o fileio.o \
@DEBUGFS_CMT@ inode_io.o namei.o write_bb_file.o
-@RESIZER_CMT@RESIZE_LIB_OBJS = rs_bitmap.o dupfs.o test_io.o
+MK_CMDS= _SS_DIR_OVERRIDE=../ss ../ss/mk_cmds
+
+@RESIZER_CMT@RESIZE_LIB_OBJS = dupfs.o test_io.o
@IMAGER_CMT@E2IMAGE_LIB_OBJS = imager.o
@@ -28,6 +30,8 @@
bmap.o \
check_desc.o \
closefs.o \
+ crc16.o \
+ csum.o \
dblist.o \
dblist_dir.o \
dirblock.o \
@@ -35,6 +39,7 @@
dir_iterate.o \
expanddir.o \
ext_attr.o \
+ extent.o \
finddev.o \
flushb.o \
freefs.o \
@@ -82,7 +87,8 @@
$(srcdir)/bmap.c \
$(srcdir)/check_desc.c \
$(srcdir)/closefs.c \
- $(srcdir)/cmp_bitmaps.c \
+ $(srcdir)/crc16.c \
+ $(srcdir)/csum.c \
$(srcdir)/dblist.c \
$(srcdir)/dblist_dir.c \
$(srcdir)/dirblock.c \
@@ -91,6 +97,7 @@
$(srcdir)/dupfs.c \
$(srcdir)/expanddir.c \
$(srcdir)/ext_attr.c \
+ $(srcdir)/extent.c \
$(srcdir)/fileio.c \
$(srcdir)/finddev.c \
$(srcdir)/flushb.c \
@@ -120,21 +127,21 @@
$(srcdir)/read_bb.c \
$(srcdir)/read_bb_file.c \
$(srcdir)/res_gdt.c \
- $(srcdir)/rs_bitmap.c \
$(srcdir)/rw_bitmaps.c \
$(srcdir)/swapfs.c \
$(srcdir)/tdb.c \
$(srcdir)/test_io.c \
+ $(srcdir)/tst_badblocks.c \
+ $(srcdir)/tst_bitops.c \
+ $(srcdir)/tst_byteswap.c \
+ $(srcdir)/tst_csum.c \
+ $(srcdir)/tst_getsize.c \
+ $(srcdir)/tst_iscan.c \
$(srcdir)/unix_io.c \
$(srcdir)/unlink.c \
$(srcdir)/valid_blk.c \
$(srcdir)/version.c \
- $(srcdir)/write_bb_file.c \
- $(srcdir)/tst_badblocks.c \
- $(srcdir)/tst_bitops.c \
- $(srcdir)/tst_byteswap.c \
- $(srcdir)/tst_getsize.c \
- $(srcdir)/tst_iscan.c
+ $(srcdir)/write_bb_file.c
HFILES= bitops.h ext2fs.h ext2_io.h ext2_fs.h ext2_ext_attr.h ext3_extents.h \
tdb.h
@@ -187,46 +194,42 @@
@echo " CONFIG.STATUS $@"
@cd $(top_builddir); CONFIG_FILES=lib/ext2fs/ext2fs.pc ./config.status
-tst_badblocks: tst_badblocks.o freefs.o \
- read_bb_file.o write_bb_file.o badblocks.o
+tst_badblocks: tst_badblocks.o $(STATIC_LIBEXT2FS)
@echo " LD $@"
- @$(CC) -o tst_badblocks tst_badblocks.o freefs.o \
- read_bb_file.o write_bb_file.o badblocks.o \
- inline.o bitops.o gen_bitmap.o $(LIBCOM_ERR)
+ @$(CC) -o tst_badblocks tst_badblocks.o $(STATIC_LIBEXT2FS) \
+ $(LIBCOM_ERR)
-tst_icount: icount.c initialize.o $(STATIC_LIBEXT2FS)
+tst_icount: $(srcdir)/icount.c $(STATIC_LIBEXT2FS)
@echo " LD $@"
- @$(CC) -o tst_icount $(srcdir)/icount.c initialize.o \
- -DDEBUG $(ALL_CFLAGS) \
+ @$(CC) -o tst_icount $(srcdir)/icount.c -DDEBUG $(ALL_CFLAGS) \
$(STATIC_LIBEXT2FS) $(LIBCOM_ERR)
-tst_iscan: tst_iscan.o inode.o badblocks.o test_io.o $(STATIC_LIBEXT2FS)
+tst_iscan: tst_iscan.o $(STATIC_LIBEXT2FS)
@echo " LD $@"
- @$(CC) -o tst_iscan tst_iscan.o inode.o badblocks.o test_io.o \
- $(STATIC_LIBEXT2FS) $(LIBCOM_ERR)
+ @$(CC) -o tst_iscan tst_iscan.o $(STATIC_LIBEXT2FS) $(LIBCOM_ERR)
-tst_getsize: tst_getsize.o getsize.o $(STATIC_LIBEXT2FS)
+tst_getsize: tst_getsize.o $(STATIC_LIBEXT2FS)
@echo " LD $@"
- @$(CC) -o tst_getsize tst_getsize.o getsize.o $(STATIC_LIBEXT2FS) \
+ @$(CC) -o tst_getsize tst_getsize.o $(STATIC_LIBEXT2FS) \
$(LIBCOM_ERR)
tst_ismounted: $(srcdir)/ismounted.c $(STATIC_LIBEXT2FS)
@echo " LD $@"
@$(CC) -o tst_ismounted $(srcdir)/ismounted.c -DDEBUG $(ALL_CFLAGS) $(LIBCOM_ERR)
-tst_byteswap: tst_byteswap.o bitops.o $(STATIC_LIBEXT2FS)
+tst_byteswap: tst_byteswap.o $(STATIC_LIBEXT2FS)
@echo " LD $@"
- @$(CC) -o tst_byteswap tst_byteswap.o bitops.o $(STATIC_LIBEXT2FS) \
+ @$(CC) -o tst_byteswap tst_byteswap.o $(STATIC_LIBEXT2FS) \
$(LIBCOM_ERR)
-tst_bitops: tst_bitops.o inline.o $(STATIC_LIBEXT2FS)
+tst_bitops: tst_bitops.o $(STATIC_LIBEXT2FS)
@echo " LD $@"
- @$(CC) -o tst_bitops tst_bitops.o inline.o $(ALL_CFLAGS) \
+ @$(CC) -o tst_bitops tst_bitops.o $(ALL_CFLAGS) \
$(STATIC_LIBEXT2FS) $(LIBCOM_ERR)
-tst_getsectsize: tst_getsectsize.o getsectsize.o $(STATIC_LIBEXT2FS)
+tst_getsectsize: tst_getsectsize.o $(STATIC_LIBEXT2FS)
@echo " LD $@"
- @$(CC) -o tst_sectgetsize tst_getsectsize.o getsectsize.o \
+ @$(CC) -o tst_sectgetsize tst_getsectsize.o \
$(STATIC_LIBEXT2FS) $(LIBCOM_ERR)
tst_types: tst_types.o ext2_types.h
@@ -241,19 +244,85 @@
@echo " LD $@"
@$(CC) -o ext2_tdbtool tdbtool.o tdb.o
+extent_dbg.c: $(srcdir)/extent_dbg.ct
+ @echo " MK_CMDS $<"
+ @$(MK_CMDS) $(srcdir)/extent_dbg.ct
+
+debug_cmds.c debug_cmds.h: $(top_srcdir)/debugfs/debug_cmds.ct
+ @echo " MK_CMDS $<@"
+ @$(MK_CMDS) $(top_srcdir)/debugfs/debug_cmds.ct
+
+DEBUG_OBJS= debug_cmds.o debugfs.o util.o ncheck.o icheck.o ls.o \
+ lsdel.o dump.o set_fields.o logdump.o htree.o unused.o
+
+debugfs.o: $(top_srcdir)/debugfs/debugfs.c
+ @echo " CC $<"
+ @$(CC) $(ALL_CFLAGS) -c $< -o $@
+
+util.o: $(top_srcdir)/debugfs/util.c
+ @echo " CC $<"
+ @$(CC) $(ALL_CFLAGS) -c $< -o $@
+
+ncheck.o: $(top_srcdir)/debugfs/ncheck.c
+ @echo " CC $<"
+ @$(CC) $(ALL_CFLAGS) -c $< -o $@
+
+icheck.o: $(top_srcdir)/debugfs/icheck.c
+ @echo " CC $<"
+ @$(CC) $(ALL_CFLAGS) -c $< -o $@
+
+ls.o: $(top_srcdir)/debugfs/ls.c
+ @echo " CC $<"
+ @$(CC) $(ALL_CFLAGS) -c $< -o $@
+
+lsdel.o: $(top_srcdir)/debugfs/lsdel.c
+ @echo " CC $<"
+ @$(CC) $(ALL_CFLAGS) -c $< -o $@
+
+dump.o: $(top_srcdir)/debugfs/dump.c
+ @echo " CC $<"
+ @$(CC) $(ALL_CFLAGS) -c $< -o $@
+
+set_fields.o: $(top_srcdir)/debugfs/set_fields.c
+ @echo " CC $<"
+ @$(CC) $(ALL_CFLAGS) -c $< -o $@
+
+logdump.o: $(top_srcdir)/debugfs/logdump.c
+ @echo " CC $<"
+ @$(CC) $(ALL_CFLAGS) -c $< -o $@
+
+htree.o: $(top_srcdir)/debugfs/htree.c
+ @echo " CC $<"
+ @$(CC) $(ALL_CFLAGS) -c $< -o $@
+
+unused.o: $(top_srcdir)/debugfs/unused.c
+ @echo " CC $<"
+ @$(CC) $(ALL_CFLAGS) -c $< -o $@
+
+tst_extents: $(srcdir)/extent.c extent_dbg.c $(DEBUG_OBJS) $(LIBSS) $(LIBE2P) $(DEPLIBUUID) $(DEPLIBBLKID)
+ @echo " LD $@"
+ @$(CC) -o tst_extents $(srcdir)/extent.c extent_dbg.c \
+ $(ALL_CFLAGS) -DDEBUG $(DEBUG_OBJS) $(LIBSS) $(LIBE2P) \
+ $(LIBUUID) $(STATIC_LIBEXT2FS) $(LIBBLKID) $(LIBCOM_ERR) \
+ -I $(top_srcdir)/debugfs
+
+tst_csum: tst_csum.c csum.c $(STATIC_LIBEXT2FS)
+ @echo " LD $@"
+ @$(CC) -o tst_csum $(srcdir)/csum.c $(srcdir)/tst_csum.c -DDEBUG \
+ $(ALL_CFLAGS) $(STATIC_LIBEXT2FS) $(LIBCOM_ERR)
+
mkjournal: mkjournal.c $(STATIC_LIBEXT2FS)
@echo " LD $@"
@$(CC) -o mkjournal $(srcdir)/mkjournal.c -DDEBUG $(STATIC_LIBEXT2FS) $(LIBCOM_ERR) $(ALL_CFLAGS)
-check:: tst_bitops tst_badblocks tst_iscan @SWAPFS_CMT@ tst_byteswap \
- tst_types tst_icount tst_super_size
+check:: tst_bitops tst_badblocks tst_iscan tst_types tst_icount tst_super_size tst_types tst_csum
LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_bitops
LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_badblocks
LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_iscan
-@SWAPFS_CMT@ LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_byteswap
LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_types
LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_icount
LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_super_size
+ LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_csum
installdirs::
@echo " MKINSTALLDIRS $(libdir) $(includedir)/ext2fs"
@@ -285,8 +354,8 @@
$(RM) -f \#* *.s *.o *.a *~ *.bak core profiled/* checker/* \
tst_badblocks tst_iscan ext2_err.et ext2_err.c ext2_err.h \
tst_byteswap tst_ismounted tst_getsize tst_sectgetsize \
- tst_bitops tst_types tst_icount tst_super_size \
- ext2_tdbtool mkjournal \
+ tst_bitops tst_types tst_icount tst_super_size tst_csum \
+ ext2_tdbtool mkjournal debug_cmds.c \
../libext2fs.a ../libext2fs_p.a ../libext2fs_chk.a
mostlyclean:: clean
@@ -309,277 +378,344 @@
alloc.o: $(srcdir)/alloc.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
alloc_sb.o: $(srcdir)/alloc_sb.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
alloc_stats.o: $(srcdir)/alloc_stats.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
alloc_tables.o: $(srcdir)/alloc_tables.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
badblocks.o: $(srcdir)/badblocks.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
$(srcdir)/ext2fs.h $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
- $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \
+ $(srcdir)/bitops.h
bb_compat.o: $(srcdir)/bb_compat.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
$(srcdir)/ext2fs.h $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
- $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \
+ $(srcdir)/bitops.h
bb_inode.o: $(srcdir)/bb_inode.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
bitmaps.o: $(srcdir)/bitmaps.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
bitops.o: $(srcdir)/bitops.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
block.o: $(srcdir)/block.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
bmap.o: $(srcdir)/bmap.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
check_desc.o: $(srcdir)/check_desc.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
closefs.o: $(srcdir)/closefs.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
$(srcdir)/ext2fs.h $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
- $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
-cmp_bitmaps.o: $(srcdir)/cmp_bitmaps.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \
+ $(srcdir)/bitops.h
+crc16.o: $(srcdir)/crc16.c $(srcdir)/crc16.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h
+csum.o: $(srcdir)/csum.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h $(srcdir)/crc16.h
dblist.o: $(srcdir)/dblist.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
$(srcdir)/ext2fs.h $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
- $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \
+ $(srcdir)/bitops.h
dblist_dir.o: $(srcdir)/dblist_dir.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
$(srcdir)/ext2fs.h $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
- $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \
+ $(srcdir)/bitops.h
dirblock.o: $(srcdir)/dirblock.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
dirhash.o: $(srcdir)/dirhash.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
dir_iterate.o: $(srcdir)/dir_iterate.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
$(srcdir)/ext2fs.h $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
- $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \
+ $(srcdir)/bitops.h
dupfs.o: $(srcdir)/dupfs.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
$(srcdir)/ext2fs.h $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
- $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \
+ $(srcdir)/bitops.h
expanddir.o: $(srcdir)/expanddir.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
ext_attr.o: $(srcdir)/ext_attr.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2_ext_attr.h \
$(srcdir)/ext2fs.h $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
- $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \
+ $(srcdir)/bitops.h
+extent.o: $(srcdir)/extent.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \
+ $(srcdir)/bitops.h $(srcdir)/e2image.h $(top_srcdir)/lib/ss/ss.h \
+ $(top_builddir)/lib/ss/ss_err.h
fileio.o: $(srcdir)/fileio.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
finddev.o: $(srcdir)/finddev.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
flushb.o: $(srcdir)/flushb.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
freefs.o: $(srcdir)/freefs.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
$(srcdir)/ext2fs.h $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
- $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \
+ $(srcdir)/bitops.h
gen_bitmap.o: $(srcdir)/gen_bitmap.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
get_pathname.o: $(srcdir)/get_pathname.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
getsize.o: $(srcdir)/getsize.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
getsectsize.o: $(srcdir)/getsectsize.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
icount.o: $(srcdir)/icount.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h \
- $(srcdir)/tdb.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h $(srcdir)/tdb.h
ind_block.o: $(srcdir)/ind_block.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
initialize.o: $(srcdir)/initialize.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
inline.o: $(srcdir)/inline.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
inode.o: $(srcdir)/inode.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
$(srcdir)/ext2fs.h $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
- $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h $(srcdir)/e2image.h
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \
+ $(srcdir)/bitops.h $(srcdir)/e2image.h
inode_io.o: $(srcdir)/inode_io.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
imager.o: $(srcdir)/imager.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
io_manager.o: $(srcdir)/io_manager.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
ismounted.o: $(srcdir)/ismounted.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
link.o: $(srcdir)/link.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
llseek.o: $(srcdir)/llseek.c $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/ext2_io.h
lookup.o: $(srcdir)/lookup.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
mkdir.o: $(srcdir)/mkdir.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
mkjournal.o: $(srcdir)/mkjournal.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/e2p/e2p.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext2fs.h $(srcdir)/ext3_extents.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
- $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h \
- $(srcdir)/jfs_user.h $(srcdir)/kernel-jbd.h $(srcdir)/jfs_compat.h \
- $(srcdir)/kernel-list.h
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \
+ $(srcdir)/bitops.h $(srcdir)/jfs_user.h $(srcdir)/kernel-jbd.h \
+ $(srcdir)/jfs_compat.h $(srcdir)/kernel-list.h
namei.o: $(srcdir)/namei.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
native.o: $(srcdir)/native.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
newdir.o: $(srcdir)/newdir.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
openfs.o: $(srcdir)/openfs.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h \
- $(srcdir)/e2image.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h $(srcdir)/e2image.h
read_bb.o: $(srcdir)/read_bb.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
read_bb_file.o: $(srcdir)/read_bb_file.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
res_gdt.o: $(srcdir)/res_gdt.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
-rs_bitmap.o: $(srcdir)/rs_bitmap.c $(srcdir)/ext2_fs.h \
- $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
- $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
rw_bitmaps.o: $(srcdir)/rw_bitmaps.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h \
- $(srcdir)/e2image.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h $(srcdir)/e2image.h
swapfs.o: $(srcdir)/swapfs.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h \
- $(srcdir)/ext2_ext_attr.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
tdb.o: $(srcdir)/tdb.c $(srcdir)/tdb.h
test_io.o: $(srcdir)/test_io.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
-unix_io.o: $(srcdir)/unix_io.c $(srcdir)/ext2_fs.h \
- $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
- $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
-unlink.o: $(srcdir)/unlink.c $(srcdir)/ext2_fs.h \
- $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
- $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
-valid_blk.o: $(srcdir)/valid_blk.c $(srcdir)/ext2_fs.h \
- $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
- $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
-version.o: $(srcdir)/version.c $(srcdir)/ext2_fs.h \
- $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
- $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h \
- $(top_srcdir)/version.h
-write_bb_file.o: $(srcdir)/write_bb_file.c $(srcdir)/ext2_fs.h \
- $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
- $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
tst_badblocks.o: $(srcdir)/tst_badblocks.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
tst_bitops.o: $(srcdir)/tst_bitops.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
tst_byteswap.o: $(srcdir)/tst_byteswap.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
+tst_csum.o: $(srcdir)/tst_csum.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
tst_getsize.o: $(srcdir)/tst_getsize.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
tst_iscan.o: $(srcdir)/tst_iscan.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
+unix_io.o: $(srcdir)/unix_io.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
+unlink.o: $(srcdir)/unlink.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
+valid_blk.o: $(srcdir)/valid_blk.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
+version.o: $(srcdir)/version.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h $(top_srcdir)/version.h
+write_bb_file.o: $(srcdir)/write_bb_file.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
diff --git a/lib/ext2fs/alloc_stats.c b/lib/ext2fs/alloc_stats.c
index 4088f7b..725f28d 100644
--- a/lib/ext2fs/alloc_stats.c
+++ b/lib/ext2fs/alloc_stats.c
@@ -27,6 +27,25 @@
fs->group_desc[group].bg_free_inodes_count -= inuse;
if (isdir)
fs->group_desc[group].bg_used_dirs_count += inuse;
+
+ /* We don't strictly need to be clearing these if inuse < 0
+ * (i.e. freeing inodes) but it also means something is bad. */
+ fs->group_desc[group].bg_flags &= ~(EXT2_BG_INODE_UNINIT |
+ EXT2_BG_BLOCK_UNINIT);
+ if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+ ext2_ino_t first_unused_inode = fs->super->s_inodes_per_group -
+ fs->group_desc[group].bg_itable_unused +
+ group * fs->super->s_inodes_per_group + 1;
+
+ if (ino >= first_unused_inode)
+ fs->group_desc[group].bg_itable_unused =
+ group * fs->super->s_inodes_per_group +
+ fs->super->s_inodes_per_group - ino;
+
+ ext2fs_group_desc_csum_set(fs, group);
+ }
+
fs->super->s_free_inodes_count -= inuse;
ext2fs_mark_super_dirty(fs);
ext2fs_mark_ib_dirty(fs);
@@ -46,6 +65,9 @@
else
ext2fs_unmark_block_bitmap(fs->block_map, blk);
fs->group_desc[group].bg_free_blocks_count -= inuse;
+ fs->group_desc[group].bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
+ ext2fs_group_desc_csum_set(fs, group);
+
fs->super->s_free_blocks_count -= inuse;
ext2fs_mark_super_dirty(fs);
ext2fs_mark_bb_dirty(fs);
diff --git a/lib/ext2fs/alloc_tables.c b/lib/ext2fs/alloc_tables.c
index 4ad2ba9..9b4f0e5 100644
--- a/lib/ext2fs/alloc_tables.c
+++ b/lib/ext2fs/alloc_tables.c
@@ -95,13 +95,11 @@
ext2fs_mark_block_bitmap(bmap, blk);
fs->group_desc[group].bg_inode_table = new_blk;
}
+ ext2fs_group_desc_csum_set(fs, group);
-
return 0;
}
-
-
errcode_t ext2fs_allocate_tables(ext2_filsys fs)
{
errcode_t retval;
diff --git a/lib/ext2fs/bitmaps.c b/lib/ext2fs/bitmaps.c
index 696baad..b033fa3 100644
--- a/lib/ext2fs/bitmaps.c
+++ b/lib/ext2fs/bitmaps.c
@@ -27,96 +27,31 @@
#include "ext2_fs.h"
#include "ext2fs.h"
-static errcode_t make_bitmap(__u32 start, __u32 end, __u32 real_end,
- const char *descr, char *init_map,
- ext2fs_generic_bitmap *ret)
+void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap)
{
- ext2fs_generic_bitmap bitmap;
- errcode_t retval;
- size_t size;
-
- retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap),
- &bitmap);
- if (retval)
- return retval;
-
- bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
- bitmap->fs = NULL;
- bitmap->start = start;
- bitmap->end = end;
- bitmap->real_end = real_end;
- bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
- if (descr) {
- retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description);
- if (retval) {
- ext2fs_free_mem(&bitmap);
- return retval;
- }
- strcpy(bitmap->description, descr);
- } else
- bitmap->description = 0;
-
- size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
- retval = ext2fs_get_mem(size, &bitmap->bitmap);
- if (retval) {
- ext2fs_free_mem(&bitmap->description);
- ext2fs_free_mem(&bitmap);
- return retval;
- }
-
- if (init_map)
- memcpy(bitmap->bitmap, init_map, size);
- else
- memset(bitmap->bitmap, 0, size);
- *ret = bitmap;
- return 0;
+ ext2fs_free_generic_bitmap(bitmap);
}
-errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
- __u32 end,
- __u32 real_end,
- const char *descr,
- ext2fs_generic_bitmap *ret)
+void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap)
{
- return make_bitmap(start, end, real_end, descr, 0, ret);
+ ext2fs_free_generic_bitmap(bitmap);
}
errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
ext2fs_generic_bitmap *dest)
{
- errcode_t retval;
- ext2fs_generic_bitmap new_map;
-
- retval = make_bitmap(src->start, src->end, src->real_end,
- src->description, src->bitmap, &new_map);
- if (retval)
- return retval;
- new_map->magic = src->magic;
- new_map->fs = src->fs;
- new_map->base_error_code = src->base_error_code;
- *dest = new_map;
- return 0;
+ return (ext2fs_copy_generic_bitmap(src, dest));
}
void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map)
{
- __u32 i, j;
-
- /* Protect loop from wrap-around if map->real_end is maxed */
- for (i=map->end+1, j = i - map->start;
- i <= map->real_end && i > map->end;
- i++, j++)
- ext2fs_set_bit(j, map->bitmap);
-
- return;
+ ext2fs_set_generic_bitmap_padding(map);
}
errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
const char *descr,
ext2fs_inode_bitmap *ret)
{
- ext2fs_inode_bitmap bitmap;
- errcode_t retval;
__u32 start, end, real_end;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
@@ -127,25 +62,15 @@
end = fs->super->s_inodes_count;
real_end = (EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count);
- retval = ext2fs_allocate_generic_bitmap(start, end, real_end,
- descr, &bitmap);
- if (retval)
- return retval;
-
- bitmap->magic = EXT2_ET_MAGIC_INODE_BITMAP;
- bitmap->fs = fs;
- bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK;
-
- *ret = bitmap;
- return 0;
+ return (ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_INODE_BITMAP, fs,
+ start, end, real_end,
+ descr, 0, ret));
}
errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
const char *descr,
ext2fs_block_bitmap *ret)
{
- ext2fs_block_bitmap bitmap;
- errcode_t retval;
__u32 start, end, real_end;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
@@ -157,59 +82,102 @@
real_end = (EXT2_BLOCKS_PER_GROUP(fs->super)
* fs->group_desc_count)-1 + start;
- retval = ext2fs_allocate_generic_bitmap(start, end, real_end,
- descr, &bitmap);
- if (retval)
- return retval;
-
- bitmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP;
- bitmap->fs = fs;
- bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
-
- *ret = bitmap;
- return 0;
+ return (ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP, fs,
+ start, end, real_end,
+ descr, 0, ret));
}
errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap,
ext2_ino_t end, ext2_ino_t *oend)
{
- EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_INODE_BITMAP);
-
- if (end > bitmap->real_end)
- return EXT2_ET_FUDGE_INODE_BITMAP_END;
- if (oend)
- *oend = bitmap->end;
- bitmap->end = end;
- return 0;
+
+ return (ext2fs_fudge_generic_bitmap_end(bitmap,
+ EXT2_ET_MAGIC_INODE_BITMAP,
+ EXT2_ET_FUDGE_INODE_BITMAP_END,
+ end, oend));
}
errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap,
blk_t end, blk_t *oend)
{
- EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_BLOCK_BITMAP);
-
- if (end > bitmap->real_end)
- return EXT2_ET_FUDGE_BLOCK_BITMAP_END;
- if (oend)
- *oend = bitmap->end;
- bitmap->end = end;
- return 0;
+ return (ext2fs_fudge_generic_bitmap_end(bitmap,
+ EXT2_ET_MAGIC_BLOCK_BITMAP,
+ EXT2_ET_FUDGE_BLOCK_BITMAP_END,
+ end, oend));
}
void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap)
{
- if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP))
- return;
-
- memset(bitmap->bitmap, 0,
- (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
+ ext2fs_clear_generic_bitmap(bitmap);
}
void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap)
{
- if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP))
- return;
+ ext2fs_clear_generic_bitmap(bitmap);
+}
- memset(bitmap->bitmap, 0,
- (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
+errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
+ ext2fs_inode_bitmap bmap)
+{
+ return (ext2fs_resize_generic_bitmap(EXT2_ET_MAGIC_INODE_BITMAP,
+ new_end, new_real_end, bmap));
+}
+
+errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
+ ext2fs_block_bitmap bmap)
+{
+ return (ext2fs_resize_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP,
+ new_end, new_real_end, bmap));
+}
+
+errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
+ ext2fs_block_bitmap bm2)
+{
+ return (ext2fs_compare_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP,
+ EXT2_ET_NEQ_BLOCK_BITMAP,
+ bm1, bm2));
+}
+
+errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
+ ext2fs_inode_bitmap bm2)
+{
+ return (ext2fs_compare_generic_bitmap(EXT2_ET_MAGIC_INODE_BITMAP,
+ EXT2_ET_NEQ_INODE_BITMAP,
+ bm1, bm2));
+}
+
+errcode_t ext2fs_set_inode_bitmap_range(ext2fs_inode_bitmap bmap,
+ ext2_ino_t start, unsigned int num,
+ void *in)
+{
+ return (ext2fs_set_generic_bitmap_range(bmap,
+ EXT2_ET_MAGIC_INODE_BITMAP,
+ start, num, in));
+}
+
+errcode_t ext2fs_get_inode_bitmap_range(ext2fs_inode_bitmap bmap,
+ ext2_ino_t start, unsigned int num,
+ void *out)
+{
+ return (ext2fs_get_generic_bitmap_range(bmap,
+ EXT2_ET_MAGIC_INODE_BITMAP,
+ start, num, out));
+}
+
+errcode_t ext2fs_set_block_bitmap_range(ext2fs_block_bitmap bmap,
+ blk_t start, unsigned int num,
+ void *in)
+{
+ return (ext2fs_set_generic_bitmap_range(bmap,
+ EXT2_ET_MAGIC_BLOCK_BITMAP,
+ start, num, in));
+}
+
+errcode_t ext2fs_get_block_bitmap_range(ext2fs_block_bitmap bmap,
+ blk_t start, unsigned int num,
+ void *out)
+{
+ return (ext2fs_get_generic_bitmap_range(bmap,
+ EXT2_ET_MAGIC_BLOCK_BITMAP,
+ start, num, out));
}
diff --git a/lib/ext2fs/bitops.c b/lib/ext2fs/bitops.c
index 78632c6..9c34847 100644
--- a/lib/ext2fs/bitops.c
+++ b/lib/ext2fs/bitops.c
@@ -76,16 +76,3 @@
com_err(0, errcode, "#%lu", arg);
#endif
}
-
-void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
- int code, unsigned long arg)
-{
-#ifndef OMIT_COM_ERR
- if (bitmap->description)
- com_err(0, bitmap->base_error_code+code,
- "#%lu for %s", arg, bitmap->description);
- else
- com_err(0, bitmap->base_error_code + code, "#%lu", arg);
-#endif
-}
-
diff --git a/lib/ext2fs/bitops.h b/lib/ext2fs/bitops.h
index 76f902d..d83ce8e 100644
--- a/lib/ext2fs/bitops.h
+++ b/lib/ext2fs/bitops.h
@@ -104,11 +104,18 @@
blk_t block, int num);
extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map);
-/* These two routines moved to gen_bitmap.c */
+/* These routines moved to gen_bitmap.c */
extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
__u32 bitno);
extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
blk_t bitno);
+extern int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
+ blk_t bitno);
+extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
+ blk_t block, int num);
+extern __u32 ext2fs_get_generic_bitmap_start(ext2fs_generic_bitmap bitmap);
+extern __u32 ext2fs_get_generic_bitmap_end(ext2fs_generic_bitmap bitmap);
+
/*
* The inline routines themselves...
*
@@ -267,36 +274,6 @@
}
#endif
-#ifdef EXT2FS_ENABLE_SWAPFS
-_INLINE_ __u32 ext2fs_swab32(__u32 val)
-{
-#ifdef EXT2FS_REQUIRE_486
- __asm__("bswap %0" : "=r" (val) : "0" (val));
-#else
- __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
- "rorl $16,%0\n\t" /* swap words */
- "xchgb %b0,%h0" /* swap higher bytes */
- :"=q" (val)
- : "0" (val));
-#endif
- return val;
-}
-
-_INLINE_ __u16 ext2fs_swab16(__u16 val)
-{
- __asm__("xchgb %b0,%h0" /* swap bytes */ \
- : "=q" (val) \
- : "0" (val)); \
- return val;
-}
-
-_INLINE_ __u64 ext2fs_swab64(__u64 val)
-{
- return (ext2fs_swab32(val >> 32) |
- (((__u64)ext2fs_swab32(val & 0xFFFFFFFFUL)) << 32));
-}
-#endif
-
#undef EXT2FS_ADDR
#endif /* i386 */
@@ -339,7 +316,7 @@
#endif /* __mc68000__ */
-#if !defined(_EXT2_HAVE_ASM_SWAB_) && defined(EXT2FS_ENABLE_SWAPFS)
+#if !defined(_EXT2_HAVE_ASM_SWAB_) && defined(WORDS_BIGENDIAN)
_INLINE_ __u16 ext2fs_swab16(__u16 val)
{
@@ -401,24 +378,10 @@
}
#endif
-_INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
- blk_t bitno);
-
-_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_TEST_ERROR, bitno);
- return 0;
- }
- return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap);
-}
-
_INLINE_ int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block)
{
- return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap)
- bitmap,
+ return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
block);
}
@@ -460,197 +423,77 @@
_INLINE_ void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block)
{
-#ifdef EXT2FS_DEBUG_FAST_OPS
- if ((block < bitmap->start) || (block > bitmap->end)) {
- ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
- bitmap->description);
- return;
- }
-#endif
- ext2fs_fast_set_bit(block - bitmap->start, bitmap->bitmap);
+ ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
}
_INLINE_ void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block)
{
-#ifdef EXT2FS_DEBUG_FAST_OPS
- if ((block < bitmap->start) || (block > bitmap->end)) {
- ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK,
- block, bitmap->description);
- return;
- }
-#endif
- ext2fs_fast_clear_bit(block - bitmap->start, bitmap->bitmap);
+ ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
}
_INLINE_ int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block)
{
-#ifdef EXT2FS_DEBUG_FAST_OPS
- if ((block < bitmap->start) || (block > bitmap->end)) {
- ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
- block, bitmap->description);
- return 0;
- }
-#endif
- return ext2fs_test_bit(block - bitmap->start, bitmap->bitmap);
+ return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+ block);
}
_INLINE_ void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
-#ifdef EXT2FS_DEBUG_FAST_OPS
- if ((inode < bitmap->start) || (inode > bitmap->end)) {
- ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_MARK,
- inode, bitmap->description);
- return;
- }
-#endif
- ext2fs_fast_set_bit(inode - bitmap->start, bitmap->bitmap);
+ ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
}
_INLINE_ void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
-#ifdef EXT2FS_DEBUG_FAST_OPS
- if ((inode < bitmap->start) || (inode > bitmap->end)) {
- ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_UNMARK,
- inode, bitmap->description);
- return;
- }
-#endif
- ext2fs_fast_clear_bit(inode - bitmap->start, bitmap->bitmap);
+ ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
}
_INLINE_ int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
-#ifdef EXT2FS_DEBUG_FAST_OPS
- if ((inode < bitmap->start) || (inode > bitmap->end)) {
- ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_TEST,
- inode, bitmap->description);
- return 0;
- }
-#endif
- return ext2fs_test_bit(inode - bitmap->start, bitmap->bitmap);
+ return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+ inode);
}
_INLINE_ blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
{
- return bitmap->start;
+ return ext2fs_get_generic_bitmap_start((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
{
- return bitmap->start;
+ return ext2fs_get_generic_bitmap_start((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
{
- return bitmap->end;
+ return ext2fs_get_generic_bitmap_end((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
{
- return bitmap->end;
-}
-
-_INLINE_ int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num)
-{
- int i;
-
- if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
- ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
- block, bitmap->description);
- return 0;
- }
- for (i=0; i < num; i++) {
- if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
- return 0;
- }
- return 1;
+ return ext2fs_get_generic_bitmap_end((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num)
{
- int i;
-
-#ifdef EXT2FS_DEBUG_FAST_OPS
- if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
- ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
- block, bitmap->description);
- return 0;
- }
-#endif
- for (i=0; i < num; i++) {
- if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
- return 0;
- }
- return 1;
-}
-
-_INLINE_ void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num)
-{
- int i;
-
- if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
- ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
- bitmap->description);
- return;
- }
- for (i=0; i < num; i++)
- ext2fs_fast_set_bit(block + i - bitmap->start, bitmap->bitmap);
+ return ext2fs_test_block_bitmap_range(bitmap, block, num);
}
_INLINE_ void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num)
{
- int i;
-
-#ifdef EXT2FS_DEBUG_FAST_OPS
- if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
- ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
- bitmap->description);
- return;
- }
-#endif
- for (i=0; i < num; i++)
- ext2fs_fast_set_bit(block + i - bitmap->start, bitmap->bitmap);
-}
-
-_INLINE_ void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
- blk_t block, int num)
-{
- int i;
-
- if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
- ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
- bitmap->description);
- return;
- }
- for (i=0; i < num; i++)
- ext2fs_fast_clear_bit(block + i - bitmap->start,
- bitmap->bitmap);
+ ext2fs_mark_block_bitmap_range(bitmap, block, num);
}
_INLINE_ void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num)
{
- int i;
-
-#ifdef EXT2FS_DEBUG_FAST_OPS
- if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
- ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
- bitmap->description);
- return;
- }
-#endif
- for (i=0; i < num; i++)
- ext2fs_fast_clear_bit(block + i - bitmap->start,
- bitmap->bitmap);
+ ext2fs_unmark_block_bitmap_range(bitmap, block, num);
}
#undef _INLINE_
#endif
diff --git a/lib/ext2fs/block.c b/lib/ext2fs/block.c
index 07a6415..279a33f 100644
--- a/lib/ext2fs/block.c
+++ b/lib/ext2fs/block.c
@@ -36,6 +36,26 @@
void *priv_data;
};
+#define check_for_ro_violation_return(ctx, ret) \
+ do { \
+ if (((ctx)->flags & BLOCK_FLAG_READ_ONLY) && \
+ ((ret) & BLOCK_CHANGED)) { \
+ (ctx)->errcode = EXT2_ET_RO_BLOCK_ITERATE; \
+ ret |= BLOCK_ABORT | BLOCK_ERROR; \
+ return ret; \
+ } \
+ } while (0)
+
+#define check_for_ro_violation_goto(ctx, ret, label) \
+ do { \
+ if (((ctx)->flags & BLOCK_FLAG_READ_ONLY) && \
+ ((ret) & BLOCK_CHANGED)) { \
+ (ctx)->errcode = EXT2_ET_RO_BLOCK_ITERATE; \
+ ret |= BLOCK_ABORT | BLOCK_ERROR; \
+ goto label; \
+ } \
+ } while (0)
+
static int block_iterate_ind(blk_t *ind_block, blk_t ref_block,
int ref_offset, struct block_context *ctx)
{
@@ -49,6 +69,7 @@
ret = (*ctx->func)(ctx->fs, ind_block,
BLOCK_COUNT_IND, ref_block,
ref_offset, ctx->priv_data);
+ check_for_ro_violation_return(ctx, ret);
if (!*ind_block || (ret & BLOCK_ABORT)) {
ctx->bcount += limit;
return ret;
@@ -95,6 +116,7 @@
offset += sizeof(blk_t);
}
}
+ check_for_ro_violation_return(ctx, changed);
if (changed & BLOCK_CHANGED) {
ctx->errcode = ext2fs_write_ind_block(ctx->fs, *ind_block,
ctx->ind_buf);
@@ -107,6 +129,7 @@
ret |= (*ctx->func)(ctx->fs, ind_block,
BLOCK_COUNT_IND, ref_block,
ref_offset, ctx->priv_data);
+ check_for_ro_violation_return(ctx, ret);
return ret;
}
@@ -123,6 +146,7 @@
ret = (*ctx->func)(ctx->fs, dind_block,
BLOCK_COUNT_DIND, ref_block,
ref_offset, ctx->priv_data);
+ check_for_ro_violation_return(ctx, ret);
if (!*dind_block || (ret & BLOCK_ABORT)) {
ctx->bcount += limit*limit;
return ret;
@@ -171,6 +195,7 @@
offset += sizeof(blk_t);
}
}
+ check_for_ro_violation_return(ctx, changed);
if (changed & BLOCK_CHANGED) {
ctx->errcode = ext2fs_write_ind_block(ctx->fs, *dind_block,
ctx->dind_buf);
@@ -183,6 +208,7 @@
ret |= (*ctx->func)(ctx->fs, dind_block,
BLOCK_COUNT_DIND, ref_block,
ref_offset, ctx->priv_data);
+ check_for_ro_violation_return(ctx, ret);
return ret;
}
@@ -199,6 +225,7 @@
ret = (*ctx->func)(ctx->fs, tind_block,
BLOCK_COUNT_TIND, ref_block,
ref_offset, ctx->priv_data);
+ check_for_ro_violation_return(ctx, ret);
if (!*tind_block || (ret & BLOCK_ABORT)) {
ctx->bcount += limit*limit*limit;
return ret;
@@ -247,6 +274,7 @@
offset += sizeof(blk_t);
}
}
+ check_for_ro_violation_return(ctx, changed);
if (changed & BLOCK_CHANGED) {
ctx->errcode = ext2fs_write_ind_block(ctx->fs, *tind_block,
ctx->tind_buf);
@@ -259,7 +287,7 @@
ret |= (*ctx->func)(ctx->fs, tind_block,
BLOCK_COUNT_TIND, ref_block,
ref_offset, ctx->priv_data);
-
+ check_for_ro_violation_return(ctx, ret);
return ret;
}
@@ -276,9 +304,7 @@
void *priv_data)
{
int i;
- int got_inode = 0;
int ret = 0;
- blk_t blocks[EXT2_N_BLOCKS]; /* directory data blocks */
struct ext2_inode inode;
errcode_t retval;
struct block_context ctx;
@@ -286,23 +312,19 @@
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+ ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
+ if (ctx.errcode)
+ return ctx.errcode;
+
/*
* Check to see if we need to limit large files
*/
if (flags & BLOCK_FLAG_NO_LARGE) {
- ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
- if (ctx.errcode)
- return ctx.errcode;
- got_inode = 1;
if (!LINUX_S_ISDIR(inode.i_mode) &&
(inode.i_size_high != 0))
return EXT2_ET_FILE_TOO_BIG;
}
- retval = ext2fs_get_blocks(fs, ino, blocks);
- if (retval)
- return retval;
-
limit = fs->blocksize >> 2;
ctx.fs = fs;
@@ -325,10 +347,6 @@
*/
if ((fs->super->s_creator_os == EXT2_OS_HURD) &&
!(flags & BLOCK_FLAG_DATA_ONLY)) {
- ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
- if (ctx.errcode)
- goto abort_exit;
- got_inode = 1;
if (inode.osd1.hurd1.h_i_translator) {
ret |= (*ctx.func)(fs,
&inode.osd1.hurd1.h_i_translator,
@@ -336,36 +354,98 @@
0, 0, priv_data);
if (ret & BLOCK_ABORT)
goto abort_exit;
+ check_for_ro_violation_goto(&ctx, ret, abort_exit);
}
}
+ if (inode.i_flags & EXT4_EXTENTS_FL) {
+ ext2_extent_handle_t handle;
+ struct ext2fs_extent extent;
+ e2_blkcnt_t blockcnt;
+ blk_t blk;
+ int op = EXT2_EXTENT_ROOT;
+ unsigned int j;
+
+ if (!(flags & BLOCK_FLAG_READ_ONLY))
+ return EXT2_ET_EXTENT_NOT_SUPPORTED;
+
+ ctx.errcode = ext2fs_extent_open(fs, ino, &handle);
+ if (ctx.errcode)
+ goto abort_exit;
+
+ while (1) {
+ ctx.errcode = ext2fs_extent_get(handle, op, &extent);
+ if (ctx.errcode) {
+ if (ctx.errcode == EXT2_ET_EXTENT_NO_NEXT)
+ ctx.errcode = 0;
+ break;
+ }
+
+ op = EXT2_EXTENT_NEXT;
+ blk = extent.e_pblk;
+ if (!(extent.e_flags & EXT2_EXTENT_FLAGS_LEAF) &&
+ !(ctx.flags & BLOCK_FLAG_DATA_ONLY) &&
+ ((!(extent.e_flags &
+ EXT2_EXTENT_FLAGS_SECOND_VISIT) &&
+ !(ctx.flags & BLOCK_FLAG_DEPTH_TRAVERSE)) ||
+ ((extent.e_flags &
+ EXT2_EXTENT_FLAGS_SECOND_VISIT) &&
+ (ctx.flags & BLOCK_FLAG_DEPTH_TRAVERSE)))) {
+ ret |= (*ctx.func)(fs, &blk,
+ -1, 0, 0, priv_data);
+ check_for_ro_violation_goto(&ctx, ret,
+ extent_errout);
+ continue;
+ }
+ for (blockcnt = extent.e_lblk, j = 0;
+ j < extent.e_len;
+ blk++, blockcnt++, j++) {
+ ret |= (*ctx.func)(fs, &blk,
+ blockcnt,
+ 0, 0, priv_data);
+ check_for_ro_violation_goto(&ctx, ret,
+ extent_errout);
+ if (ret & BLOCK_ABORT) {
+ ext2fs_extent_free(handle);
+ goto abort_exit;
+ }
+ }
+ }
+
+ extent_errout:
+ ext2fs_extent_free(handle);
+ ret |= BLOCK_ERROR | BLOCK_ABORT;
+ goto abort_exit;
+ }
+
/*
* Iterate over normal data blocks
*/
for (i = 0; i < EXT2_NDIR_BLOCKS ; i++, ctx.bcount++) {
- if (blocks[i] || (flags & BLOCK_FLAG_APPEND)) {
- ret |= (*ctx.func)(fs, &blocks[i],
+ if (inode.i_block[i] || (flags & BLOCK_FLAG_APPEND)) {
+ ret |= (*ctx.func)(fs, &inode.i_block[i],
ctx.bcount, 0, i, priv_data);
if (ret & BLOCK_ABORT)
goto abort_exit;
}
}
- if (*(blocks + EXT2_IND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
- ret |= block_iterate_ind(blocks + EXT2_IND_BLOCK,
+ check_for_ro_violation_goto(&ctx, ret, abort_exit);
+ if (inode.i_block[EXT2_IND_BLOCK] || (flags & BLOCK_FLAG_APPEND)) {
+ ret |= block_iterate_ind(&inode.i_block[EXT2_IND_BLOCK],
0, EXT2_IND_BLOCK, &ctx);
if (ret & BLOCK_ABORT)
goto abort_exit;
} else
ctx.bcount += limit;
- if (*(blocks + EXT2_DIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
- ret |= block_iterate_dind(blocks + EXT2_DIND_BLOCK,
+ if (inode.i_block[EXT2_DIND_BLOCK] || (flags & BLOCK_FLAG_APPEND)) {
+ ret |= block_iterate_dind(&inode.i_block[EXT2_DIND_BLOCK],
0, EXT2_DIND_BLOCK, &ctx);
if (ret & BLOCK_ABORT)
goto abort_exit;
} else
ctx.bcount += limit * limit;
- if (*(blocks + EXT2_TIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
- ret |= block_iterate_tind(blocks + EXT2_TIND_BLOCK,
+ if (inode.i_block[EXT2_TIND_BLOCK] || (flags & BLOCK_FLAG_APPEND)) {
+ ret |= block_iterate_tind(&inode.i_block[EXT2_TIND_BLOCK],
0, EXT2_TIND_BLOCK, &ctx);
if (ret & BLOCK_ABORT)
goto abort_exit;
@@ -373,13 +453,6 @@
abort_exit:
if (ret & BLOCK_CHANGED) {
- if (!got_inode) {
- retval = ext2fs_read_inode(fs, ino, &inode);
- if (retval)
- return retval;
- }
- for (i=0; i < EXT2_N_BLOCKS; i++)
- inode.i_block[i] = blocks[i];
retval = ext2fs_write_inode(fs, ino, &inode);
if (retval)
return retval;
diff --git a/lib/ext2fs/bmap.c b/lib/ext2fs/bmap.c
index 754fc49..5fe0986 100644
--- a/lib/ext2fs/bmap.c
+++ b/lib/ext2fs/bmap.c
@@ -14,6 +14,7 @@
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
+#include <errno.h>
#include "ext2_fs.h"
#include "ext2fs.h"
@@ -51,10 +52,8 @@
if (flags & BMAP_SET) {
b = *ret_blk;
-#ifdef EXT2FS_ENABLE_SWAPFS
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
- b = ext2fs_swab32(b);
+#ifdef WORDS_BIGENDIAN
+ b = ext2fs_swab32(b);
#endif
((blk_t *) block_buf)[nr] = b;
return io_channel_write_blk(fs->io, ind, 1, block_buf);
@@ -62,10 +61,8 @@
b = ((blk_t *) block_buf)[nr];
-#ifdef EXT2FS_ENABLE_SWAPFS
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
- b = ext2fs_swab32(b);
+#ifdef WORDS_BIGENDIAN
+ b = ext2fs_swab32(b);
#endif
if (!b && (flags & BMAP_ALLOC)) {
@@ -75,13 +72,11 @@
if (retval)
return retval;
-#ifdef EXT2FS_ENABLE_SWAPFS
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
- ((blk_t *) block_buf)[nr] = ext2fs_swab32(b);
- else
+#ifdef WORDS_BIGENDIAN
+ ((blk_t *) block_buf)[nr] = ext2fs_swab32(b);
+#else
+ ((blk_t *) block_buf)[nr] = b;
#endif
- ((blk_t *) block_buf)[nr] = b;
retval = io_channel_write_blk(fs->io, ind, 1, block_buf);
if (retval)
@@ -134,13 +129,14 @@
return retval;
}
-errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
- char *block_buf, int bmap_flags, blk_t block,
- blk_t *phys_blk)
+errcode_t ext2fs_bmap2(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
+ char *block_buf, int bmap_flags, blk64_t block,
+ int *ret_flags, blk64_t *phys_blk)
{
struct ext2_inode inode_buf;
+ ext2_extent_handle_t handle = 0;
blk_t addr_per_block;
- blk_t b;
+ blk_t b, blk32;
char *buf = 0;
errcode_t retval = 0;
int blocks_alloc = 0, inode_dirty = 0;
@@ -148,6 +144,9 @@
if (!(bmap_flags & BMAP_SET))
*phys_blk = 0;
+ if (ret_flags)
+ *ret_flags = 0;
+
/* Read inode structure if necessary */
if (!inode) {
retval = ext2fs_read_inode(fs, ino, &inode_buf);
@@ -157,6 +156,37 @@
}
addr_per_block = (blk_t) fs->blocksize >> 2;
+ if (inode->i_flags & EXT4_EXTENTS_FL) {
+ struct ext2fs_extent extent;
+ unsigned int offset;
+
+ if (bmap_flags & BMAP_SET) {
+ retval = EXT2_ET_EXTENT_NOT_SUPPORTED;
+ goto done;
+ }
+ retval = ext2fs_extent_open(fs, ino, &handle);
+ if (retval)
+ goto done;
+ retval = ext2fs_extent_goto(handle, block);
+ if (retval) {
+ /* If the extent is not found, return phys_blk = 0 */
+ if (retval == EXT2_ET_EXTENT_NOT_FOUND)
+ retval = 0;
+ goto done;
+ }
+ retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent);
+ if (retval)
+ goto done;
+ offset = block - extent.e_lblk;
+ if (block >= extent.e_lblk && (offset <= extent.e_len)) {
+ *phys_blk = extent.e_pblk + offset;
+ if (ret_flags && extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT)
+ *ret_flags |= BMAP_RET_UNINIT;
+ }
+ retval = 0;
+ goto done;
+ }
+
if (!block_buf) {
retval = ext2fs_get_array(2, fs->blocksize, &buf);
if (retval)
@@ -167,10 +197,8 @@
if (block < EXT2_NDIR_BLOCKS) {
if (bmap_flags & BMAP_SET) {
b = *phys_blk;
-#ifdef EXT2FS_ENABLE_SWAPFS
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
- b = ext2fs_swab32(b);
+#ifdef WORDS_BIGENDIAN
+ b = ext2fs_swab32(b);
#endif
inode_bmap(inode, block) = b;
inode_dirty++;
@@ -193,6 +221,7 @@
/* Indirect block */
block -= EXT2_NDIR_BLOCKS;
+ blk32 = *phys_blk;
if (block < addr_per_block) {
b = inode_bmap(inode, EXT2_IND_BLOCK);
if (!b) {
@@ -210,7 +239,9 @@
blocks_alloc++;
}
retval = block_ind_bmap(fs, bmap_flags, b, block_buf,
- &blocks_alloc, block, phys_blk);
+ &blocks_alloc, block, &blk32);
+ if (retval == 0)
+ *phys_blk = blk32;
goto done;
}
@@ -233,7 +264,9 @@
blocks_alloc++;
}
retval = block_dind_bmap(fs, bmap_flags, b, block_buf,
- &blocks_alloc, block, phys_blk);
+ &blocks_alloc, block, &blk32);
+ if (retval == 0)
+ *phys_blk = blk32;
goto done;
}
@@ -255,10 +288,14 @@
blocks_alloc++;
}
retval = block_tind_bmap(fs, bmap_flags, b, block_buf,
- &blocks_alloc, block, phys_blk);
+ &blocks_alloc, block, &blk32);
+ if (retval == 0)
+ *phys_blk = blk32;
done:
if (buf)
ext2fs_free_mem(&buf);
+ if (handle)
+ ext2fs_extent_free(handle);
if ((retval == 0) && (blocks_alloc || inode_dirty)) {
inode->i_blocks += (blocks_alloc * fs->blocksize) / 512;
retval = ext2fs_write_inode(fs, ino, inode);
@@ -266,5 +303,19 @@
return retval;
}
+errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
+ char *block_buf, int bmap_flags, blk_t block,
+ blk_t *phys_blk)
+{
+ errcode_t ret;
+ blk64_t ret_blk;
-
+ ret = ext2fs_bmap2(fs, ino, inode, block_buf, bmap_flags, block,
+ 0, &ret_blk);
+ if (ret)
+ return ret;
+ if (ret_blk >= ((long long) 1 << 32))
+ return EOVERFLOW;
+ *phys_blk = ret_blk;
+ return 0;
+}
diff --git a/lib/ext2fs/check_desc.c b/lib/ext2fs/check_desc.c
index 146f9e5..900b179 100644
--- a/lib/ext2fs/check_desc.c
+++ b/lib/ext2fs/check_desc.c
@@ -33,13 +33,16 @@
{
dgrp_t i;
blk_t first_block = fs->super->s_first_data_block;
- blk_t last_block;
+ blk_t last_block = fs->super->s_blocks_count-1;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
for (i = 0; i < fs->group_desc_count; i++) {
- first_block = ext2fs_group_first_block(fs, i);
- last_block = ext2fs_group_last_block(fs, i);
+ if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
+ first_block = ext2fs_group_first_block(fs, i);
+ last_block = ext2fs_group_last_block(fs, i);
+ }
/*
* Check to make sure block bitmap for group is
diff --git a/lib/ext2fs/closefs.c b/lib/ext2fs/closefs.c
index 88c515a..086c28a 100644
--- a/lib/ext2fs/closefs.c
+++ b/lib/ext2fs/closefs.c
@@ -54,11 +54,10 @@
{
blk_t group_block, super_blk = 0, old_desc_blk = 0, new_desc_blk = 0;
unsigned int meta_bg, meta_bg_size;
- int numblocks, has_super;
- int old_desc_blocks;
+ blk_t numblocks, old_desc_blocks;
+ int has_super;
- group_block = fs->super->s_first_data_block +
- (group * fs->super->s_blocks_per_group);
+ group_block = ext2fs_group_first_block(fs, group);
if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
old_desc_blocks = fs->super->s_first_meta_bg;
@@ -81,7 +80,7 @@
super_blk = group_block;
numblocks--;
}
- meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc));
+ meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
meta_bg = group / meta_bg_size;
if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
@@ -191,12 +190,11 @@
if (sgrp > ((1 << 16) - 1))
sgrp = (1 << 16) - 1;
-#ifdef EXT2FS_ENABLE_SWAPFS
- if (fs->flags & EXT2_FLAG_SWAP_BYTES)
- super_shadow->s_block_group_nr = ext2fs_swab16(sgrp);
- else
+#ifdef WORDS_BIGENDIAN
+ super_shadow->s_block_group_nr = ext2fs_swab16(sgrp);
+#else
+ fs->super->s_block_group_nr = sgrp;
#endif
- fs->super->s_block_group_nr = sgrp;
return io_channel_write_blk(fs->io, group_block, -SUPERBLOCK_SIZE,
super_shadow);
@@ -205,13 +203,16 @@
errcode_t ext2fs_flush(ext2_filsys fs)
{
- dgrp_t i,j;
+ dgrp_t i;
errcode_t retval;
unsigned long fs_state;
__u32 feature_incompat;
struct ext2_super_block *super_shadow = 0;
struct ext2_group_desc *group_shadow = 0;
+#ifdef WORDS_BIGENDIAN
struct ext2_group_desc *s, *t;
+ dgrp_t j;
+#endif
char *group_ptr;
int old_desc_blocks;
@@ -222,28 +223,23 @@
fs->super->s_wtime = fs->now ? fs->now : time(NULL);
fs->super->s_block_group_nr = 0;
-#ifdef EXT2FS_ENABLE_SWAPFS
- if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- retval = EXT2_ET_NO_MEMORY;
- retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow);
- if (retval)
- goto errout;
- retval = ext2fs_get_array(fs->blocksize, fs->desc_blocks,
- &group_shadow);
- if (retval)
- goto errout;
- memset(group_shadow, 0, (size_t) fs->blocksize *
- fs->desc_blocks);
-
- /* swap the group descriptors */
- for (j=0, s=fs->group_desc, t=group_shadow;
- j < fs->group_desc_count; j++, t++, s++) {
- *t = *s;
- ext2fs_swap_group_desc(t);
- }
- } else {
- super_shadow = fs->super;
- group_shadow = fs->group_desc;
+#ifdef WORDS_BIGENDIAN
+ retval = EXT2_ET_NO_MEMORY;
+ retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow);
+ if (retval)
+ goto errout;
+ retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
+ &group_shadow);
+ if (retval)
+ goto errout;
+ memset(group_shadow, 0, (size_t) fs->blocksize *
+ fs->desc_blocks);
+
+ /* swap the group descriptors */
+ for (j=0, s=fs->group_desc, t=group_shadow;
+ j < fs->group_desc_count; j++, t++, s++) {
+ *t = *s;
+ ext2fs_swap_group_desc(t);
}
#else
super_shadow = fs->super;
@@ -257,11 +253,9 @@
*/
fs->super->s_state &= ~EXT2_VALID_FS;
fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
-#ifdef EXT2FS_ENABLE_SWAPFS
- if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- *super_shadow = *fs->super;
- ext2fs_swap_super(super_shadow);
- }
+#ifdef WORDS_BIGENDIAN
+ *super_shadow = *fs->super;
+ ext2fs_swap_super(super_shadow);
#endif
/*
@@ -336,11 +330,9 @@
fs->super->s_block_group_nr = 0;
fs->super->s_state = fs_state;
fs->super->s_feature_incompat = feature_incompat;
-#ifdef EXT2FS_ENABLE_SWAPFS
- if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- *super_shadow = *fs->super;
- ext2fs_swap_super(super_shadow);
- }
+#ifdef WORDS_BIGENDIAN
+ *super_shadow = *fs->super;
+ ext2fs_swap_super(super_shadow);
#endif
retval = io_channel_flush(fs->io);
@@ -353,12 +345,12 @@
retval = io_channel_flush(fs->io);
errout:
fs->super->s_state = fs_state;
- if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- if (super_shadow)
- ext2fs_free_mem(&super_shadow);
- if (group_shadow)
- ext2fs_free_mem(&group_shadow);
- }
+#ifdef WORDS_BIGENDIAN
+ if (super_shadow)
+ ext2fs_free_mem(&super_shadow);
+ if (group_shadow)
+ ext2fs_free_mem(&group_shadow);
+#endif
return retval;
}
diff --git a/lib/ext2fs/cmp_bitmaps.c b/lib/ext2fs/cmp_bitmaps.c
deleted file mode 100644
index 51cc3d0..0000000
--- a/lib/ext2fs/cmp_bitmaps.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * cmp_bitmaps.c --- routines to compare inode and block bitmaps.
- *
- * Copyright (C) 1995 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
- ext2fs_block_bitmap bm2)
-{
- blk_t i;
-
- EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_BLOCK_BITMAP);
- EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_BLOCK_BITMAP);
-
- if ((bm1->start != bm2->start) ||
- (bm1->end != bm2->end) ||
- (memcmp(bm1->bitmap, bm2->bitmap,
- (size_t) (bm1->end - bm1->start)/8)))
- return EXT2_ET_NEQ_BLOCK_BITMAP;
-
- for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
- if (ext2fs_fast_test_block_bitmap(bm1, i) !=
- ext2fs_fast_test_block_bitmap(bm2, i))
- return EXT2_ET_NEQ_BLOCK_BITMAP;
-
- return 0;
-}
-
-errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
- ext2fs_inode_bitmap bm2)
-{
- ext2_ino_t i;
-
- EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_INODE_BITMAP);
- EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_INODE_BITMAP);
-
- if ((bm1->start != bm2->start) ||
- (bm1->end != bm2->end) ||
- (memcmp(bm1->bitmap, bm2->bitmap,
- (size_t) (bm1->end - bm1->start)/8)))
- return EXT2_ET_NEQ_INODE_BITMAP;
-
- for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
- if (ext2fs_fast_test_inode_bitmap(bm1, i) !=
- ext2fs_fast_test_inode_bitmap(bm2, i))
- return EXT2_ET_NEQ_INODE_BITMAP;
-
- return 0;
-}
-
diff --git a/lib/ext2fs/crc16.c b/lib/ext2fs/crc16.c
new file mode 100644
index 0000000..1b2b8a1
--- /dev/null
+++ b/lib/ext2fs/crc16.c
@@ -0,0 +1,61 @@
+/*
+ * crc16.c
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include "crc16.h"
+
+/** CRC table for the CRC-16. The poly is 0x8005 (x16 + x15 + x2 + 1) */
+__u16 const crc16_table[256] = {
+ 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
+ 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
+ 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
+ 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
+ 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
+ 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
+ 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
+ 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
+ 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
+ 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
+ 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
+ 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
+ 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
+ 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
+ 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
+ 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
+ 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
+ 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
+ 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
+ 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
+ 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
+ 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
+ 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
+ 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
+ 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
+ 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
+ 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
+ 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
+ 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
+ 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
+ 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
+ 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
+};
+
+/**
+ * Compute the CRC-16 for the data buffer
+ *
+ * @param crc previous CRC value
+ * @param buffer data pointer
+ * @param len number of bytes in the buffer
+ * @return the updated CRC value
+ */
+crc16_t crc16(crc16_t crc, const void *buffer, unsigned int len)
+{
+ const unsigned char *cp = buffer;
+
+ while (len--)
+ crc = crc16_byte(crc, *cp++);
+ return crc;
+}
diff --git a/lib/ext2fs/crc16.h b/lib/ext2fs/crc16.h
new file mode 100644
index 0000000..ab3f094
--- /dev/null
+++ b/lib/ext2fs/crc16.h
@@ -0,0 +1,45 @@
+/*
+ * crc16.h - CRC-16 routine
+ *
+ * Implements the standard CRC-16:
+ * Width 16
+ * Poly 0x8005 (x16 + x15 + x2 + 1)
+ * Init 0
+ *
+ * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#ifndef __CRC16_H
+#define __CRC16_H
+
+#include <ext2fs/ext2_types.h>
+
+extern __u16 const crc16_table[256];
+
+#ifdef WORDS_BIGENDIAN
+/* for an unknown reason, PPC treats __u16 as signed and keeps doing sign
+ * extension on the value. Instead, use only the low 16 bits of an
+ * unsigned int for holding the CRC value to avoid this.
+ */
+typedef unsigned crc16_t;
+
+static inline crc16_t crc16_byte(crc16_t crc, const unsigned char data)
+{
+ return (((crc >> 8) & 0xffU) ^ crc16_table[(crc ^ data) & 0xffU]) &
+ 0x0000ffffU;
+}
+#else
+typedef __u16 crc16_t;
+
+static inline crc16_t crc16_byte(crc16_t crc, const unsigned char data)
+{
+ return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff];
+}
+#endif
+
+extern crc16_t crc16(crc16_t crc, const void *buffer, unsigned int len);
+
+#endif /* __CRC16_H */
diff --git a/lib/ext2fs/csum.c b/lib/ext2fs/csum.c
new file mode 100644
index 0000000..0774e00
--- /dev/null
+++ b/lib/ext2fs/csum.c
@@ -0,0 +1,160 @@
+/*
+ * csum.c --- checksumming of ext3 structures
+ *
+ * Copyright (C) 2006 Cluster File Systems, Inc.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+#include "crc16.h"
+#include <assert.h>
+
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+#ifdef DEBUG
+#define STATIC
+#else
+#define STATIC static
+#endif
+
+STATIC __u16 ext2fs_group_desc_csum(ext2_filsys fs, dgrp_t group)
+{
+ __u16 crc = 0;
+ struct ext2_group_desc *desc;
+
+ desc = &fs->group_desc[group];
+
+ if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
+ int offset = offsetof(struct ext2_group_desc, bg_checksum);
+
+#ifdef WORDS_BIGENDIAN
+ struct ext2_group_desc swabdesc = *desc;
+
+ /* Have to swab back to little-endian to do the checksum */
+ ext2fs_swap_group_desc(&swabdesc);
+ desc = &swabdesc;
+
+ group = ext2fs_swab32(group);
+#endif
+ crc = crc16(~0, fs->super->s_uuid, sizeof(fs->super->s_uuid));
+ crc = crc16(crc, &group, sizeof(group));
+ crc = crc16(crc, desc, offset);
+ offset += sizeof(desc->bg_checksum); /* skip checksum */
+ assert(offset == sizeof(*desc));
+ /* for checksum of struct ext4_group_desc do the rest...*/
+ if (offset < fs->super->s_desc_size) {
+ crc = crc16(crc, (char *)desc + offset,
+ fs->super->s_desc_size - offset);
+ }
+ }
+
+ return crc;
+}
+
+int ext2fs_group_desc_csum_verify(ext2_filsys fs, dgrp_t group)
+{
+ if (fs->group_desc[group].bg_checksum !=
+ ext2fs_group_desc_csum(fs, group))
+ return 0;
+
+ return 1;
+}
+
+void ext2fs_group_desc_csum_set(ext2_filsys fs, dgrp_t group)
+{
+ fs->group_desc[group].bg_checksum = ext2fs_group_desc_csum(fs, group);
+}
+
+static __u32 find_last_inode_ingrp(ext2fs_inode_bitmap bitmap,
+ __u32 inodes_per_grp, dgrp_t grp_no)
+{
+ ext2_ino_t i, start_ino, end_ino;
+
+ start_ino = grp_no * inodes_per_grp + 1;
+ end_ino = start_ino + inodes_per_grp - 1;
+
+ for (i = end_ino; i >= start_ino; i--) {
+ if (ext2fs_fast_test_inode_bitmap(bitmap, i))
+ return i - start_ino + 1;
+ }
+ return inodes_per_grp;
+}
+
+/* update the bitmap flags, set the itable high watermark, and calculate
+ * checksums for the group descriptors */
+errcode_t ext2fs_set_gdt_csum(ext2_filsys fs)
+{
+ struct ext2_super_block *sb = fs->super;
+ struct ext2_group_desc *bg = fs->group_desc;
+ int blks, csum_flag, dirty = 0;
+ dgrp_t i;
+
+ if (!fs->inode_map)
+ return EXT2_ET_NO_INODE_BITMAP;
+
+ csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
+ if (!EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_LAZY_BG) && !csum_flag)
+ return 0;
+
+ for (i = 0; i < fs->group_desc_count; i++, bg++) {
+ int old_csum = bg->bg_checksum;
+ int old_unused = bg->bg_itable_unused;
+ int old_flags = bg->bg_flags;
+
+ /* Even if it wasn't zeroed, by the time this function is
+ * called by e2fsck we have already scanned and corrected
+ * the whole inode table so we may as well not overwrite it.
+ * This is just a hint to the kernel that it could do lazy
+ * zeroing of the inode table if mke2fs didn't do it, to help
+ * out if we need to do a full itable scan sometime later. */
+ if (!(bg->bg_flags & (EXT2_BG_INODE_UNINIT |
+ EXT2_BG_INODE_ZEROED)))
+ fs->group_desc[i].bg_flags |= EXT2_BG_INODE_ZEROED;
+
+ if (bg->bg_free_inodes_count == sb->s_inodes_per_group &&
+ i > 0 && (i < fs->group_desc_count - 1 || csum_flag)) {
+ if (!(bg->bg_flags & EXT2_BG_INODE_UNINIT))
+ bg->bg_flags |= EXT2_BG_INODE_UNINIT;
+
+ if (csum_flag)
+ bg->bg_itable_unused = sb->s_inodes_per_group;
+ } else if (csum_flag) {
+ bg->bg_flags &= ~EXT2_BG_INODE_UNINIT;
+ bg->bg_itable_unused = sb->s_inodes_per_group -
+ find_last_inode_ingrp(fs->inode_map,
+ sb->s_inodes_per_group,i);
+ }
+
+ /* skip first and last groups, or groups with GDT backups
+ * because the resize inode has blocks allocated in them. */
+ if (i == 0 || i == fs->group_desc_count - 1 ||
+ (ext2fs_bg_has_super(fs, i) && sb->s_reserved_gdt_blocks))
+ goto checksum;
+
+ blks = ext2fs_super_and_bgd_loc(fs, i, 0, 0, 0, 0);
+ if (bg->bg_free_blocks_count == blks &&
+ bg->bg_flags & EXT2_BG_INODE_UNINIT &&
+ !(bg->bg_flags & EXT2_BG_BLOCK_UNINIT))
+ bg->bg_flags |= EXT2_BG_BLOCK_UNINIT;
+checksum:
+ ext2fs_group_desc_csum_set(fs, i);
+ if (old_flags != bg->bg_flags)
+ dirty = 1;
+ if (old_unused != bg->bg_itable_unused)
+ dirty = 1;
+ if (old_csum != bg->bg_checksum)
+ dirty = 1;
+ }
+ if (dirty)
+ ext2fs_mark_super_dirty(fs);
+ return 0;
+}
diff --git a/lib/ext2fs/dblist.c b/lib/ext2fs/dblist.c
index 3bf63a0..0067cae 100644
--- a/lib/ext2fs/dblist.c
+++ b/lib/ext2fs/dblist.c
@@ -263,8 +263,6 @@
errcode_t ext2fs_dblist_get_last(ext2_dblist dblist,
struct ext2_db_entry **entry)
{
- errcode_t retval;
-
EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
if (dblist->count == 0)
diff --git a/lib/ext2fs/dir_iterate.c b/lib/ext2fs/dir_iterate.c
index 003c0a3..3e7b7b0 100644
--- a/lib/ext2fs/dir_iterate.c
+++ b/lib/ext2fs/dir_iterate.c
@@ -78,7 +78,7 @@
ctx.func = func;
ctx.priv_data = priv_data;
ctx.errcode = 0;
- retval = ext2fs_block_iterate2(fs, dir, 0, 0,
+ retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_READ_ONLY, 0,
ext2fs_process_dir_block, &ctx);
if (!block_buf)
ext2fs_free_mem(&ctx.buf);
diff --git a/lib/ext2fs/dirblock.c b/lib/ext2fs/dirblock.c
index ebfc72c..fb20fa0 100644
--- a/lib/ext2fs/dirblock.c
+++ b/lib/ext2fs/dirblock.c
@@ -25,26 +25,21 @@
errcode_t retval;
char *p, *end;
struct ext2_dir_entry *dirent;
- unsigned int name_len, rec_len, do_swap;
+ unsigned int name_len, rec_len;
retval = io_channel_read_blk(fs->io, block, 1, buf);
if (retval)
return retval;
-#ifdef EXT2FS_ENABLE_SWAPFS
- do_swap = (fs->flags & (EXT2_FLAG_SWAP_BYTES|
- EXT2_FLAG_SWAP_BYTES_READ)) != 0;
-#endif
+
p = (char *) buf;
end = (char *) buf + fs->blocksize;
while (p < end-8) {
dirent = (struct ext2_dir_entry *) p;
-#ifdef EXT2FS_ENABLE_SWAPFS
- if (do_swap) {
- dirent->inode = ext2fs_swab32(dirent->inode);
- dirent->rec_len = ext2fs_swab16(dirent->rec_len);
- dirent->name_len = ext2fs_swab16(dirent->name_len);
- }
+#ifdef WORDS_BIGENDIAN
+ dirent->inode = ext2fs_swab32(dirent->inode);
+ dirent->rec_len = ext2fs_swab16(dirent->rec_len);
+ dirent->name_len = ext2fs_swab16(dirent->name_len);
#endif
name_len = dirent->name_len;
#ifdef WORDS_BIGENDIAN
@@ -73,22 +68,12 @@
errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
void *inbuf, int flags EXT2FS_ATTR((unused)))
{
-#ifdef EXT2FS_ENABLE_SWAPFS
- int do_swap = 0;
+#ifdef WORDS_BIGENDIAN
errcode_t retval;
char *p, *end;
char *buf = 0;
struct ext2_dir_entry *dirent;
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
- do_swap = 1;
-
-#ifndef WORDS_BIGENDIAN
- if (!do_swap)
- return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
-#endif
-
retval = ext2fs_get_mem(fs->blocksize, &buf);
if (retval)
return retval;
@@ -103,15 +88,12 @@
return (EXT2_ET_DIR_CORRUPTED);
}
p += dirent->rec_len;
- if (do_swap) {
- dirent->inode = ext2fs_swab32(dirent->inode);
- dirent->rec_len = ext2fs_swab16(dirent->rec_len);
- dirent->name_len = ext2fs_swab16(dirent->name_len);
- }
-#ifdef WORDS_BIGENDIAN
+ dirent->inode = ext2fs_swab32(dirent->inode);
+ dirent->rec_len = ext2fs_swab16(dirent->rec_len);
+ dirent->name_len = ext2fs_swab16(dirent->name_len);
+
if (flags & EXT2_DIRBLOCK_V2_STRUCT)
dirent->name_len = ext2fs_swab16(dirent->name_len);
-#endif
}
retval = io_channel_write_blk(fs->io, block, 1, buf);
ext2fs_free_mem(&buf);
diff --git a/lib/ext2fs/ext2_err.et.in b/lib/ext2fs/ext2_err.et.in
index 7451242..9047a8f 100644
--- a/lib/ext2fs/ext2_err.et.in
+++ b/lib/ext2fs/ext2_err.et.in
@@ -62,8 +62,8 @@
ec EXT2_ET_MAGIC_INODE_IO_CHANNEL,
"Wrong magic number for inode io_channel structure"
-ec EXT2_ET_MAGIC_RESERVED_9,
- "Wrong magic number --- RESERVED_9"
+ec EXT2_ET_MAGIC_EXTENT_HANDLE,
+ "Wrong magic number for ext4 extent handle"
ec EXT2_ET_BAD_MAGIC,
"Bad magic number in super-block"
@@ -329,5 +329,82 @@
ec EXT2_ET_DBLIST_EMPTY,
"Ext2fs directory block list is empty"
- end
+ec EXT2_ET_RO_BLOCK_ITERATE,
+ "Attempt to modify a block mapping via a read-only block iterator"
+ec EXT2_ET_MAGIC_EXTENT_PATH,
+ "Wrong magic number for ext4 extent saved path"
+
+ec EXT2_ET_MAGIC_RESERVED_10,
+ "Wrong magic number --- RESERVED_10"
+
+ec EXT2_ET_MAGIC_RESERVED_11,
+ "Wrong magic number --- RESERVED_11"
+
+ec EXT2_ET_MAGIC_RESERVED_12,
+ "Wrong magic number --- RESERVED_12"
+
+ec EXT2_ET_MAGIC_RESERVED_13,
+ "Wrong magic number --- RESERVED_13"
+
+ec EXT2_ET_MAGIC_RESERVED_14,
+ "Wrong magic number --- RESERVED_14"
+
+ec EXT2_ET_MAGIC_RESERVED_15,
+ "Wrong magic number --- RESERVED_15"
+
+ec EXT2_ET_MAGIC_RESERVED_16,
+ "Wrong magic number --- RESERVED_16"
+
+ec EXT2_ET_MAGIC_RESERVED_17,
+ "Wrong magic number --- RESERVED_17"
+
+ec EXT2_ET_MAGIC_RESERVED_18,
+ "Wrong magic number --- RESERVED_18"
+
+ec EXT2_ET_MAGIC_RESERVED_19,
+ "Wrong magic number --- RESERVED_19"
+
+ec EXT2_ET_EXTENT_HEADER_BAD,
+ "Corrupt extent header"
+
+ec EXT2_ET_EXTENT_INDEX_BAD,
+ "Corrupt extent index"
+
+ec EXT2_ET_EXTENT_LEAF_BAD,
+ "Corrupt extent"
+
+ec EXT2_ET_EXTENT_NO_SPACE,
+ "No free space in extent map"
+
+ec EXT2_ET_INODE_NOT_EXTENT,
+ "Inode does not use extents"
+
+ec EXT2_ET_EXTENT_NO_NEXT,
+ "No 'next' extent"
+
+ec EXT2_ET_EXTENT_NO_PREV,
+ "No 'previous' extent"
+
+ec EXT2_ET_EXTENT_NO_UP,
+ "No 'up' extent"
+
+ec EXT2_ET_EXTENT_NO_DOWN,
+ "No 'down' extent"
+
+ec EXT2_ET_NO_CURRENT_NODE,
+ "No current node"
+
+ec EXT2_ET_OP_NOT_SUPPORTED,
+ "Ext2fs operation not supported"
+
+ec EXT2_ET_CANT_INSERT_EXTENT,
+ "No room to insert extent in node"
+
+ec EXT2_ET_EXTENT_NOT_FOUND,
+ "Extent not found"
+
+ec EXT2_ET_EXTENT_NOT_SUPPORTED,
+ "Operation not supported for inodes containing extents"
+
+ end
diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
index be8d773..444211d 100644
--- a/lib/ext2fs/ext2_fs.h
+++ b/lib/ext2fs/ext2_fs.h
@@ -173,6 +173,7 @@
#define EXT2_BG_INODE_UNINIT 0x0001 /* Inode table/bitmap not initialized */
#define EXT2_BG_BLOCK_UNINIT 0x0002 /* Block bitmap not initialized */
+#define EXT2_BG_INODE_ZEROED 0x0004 /* On-disk itable initialized to zero */
/*
* Data structures used by the directory indexing feature
@@ -217,6 +218,13 @@
/*
* Macro-instructions used to manage group descriptors
*/
+#define EXT2_MIN_DESC_SIZE 32
+#define EXT2_MIN_DESC_SIZE_64BIT 64
+#define EXT2_MAX_DESC_SIZE EXT2_MIN_BLOCK_SIZE
+#define EXT2_DESC_SIZE(s) \
+ ((EXT2_SB(s)->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) ? \
+ (s)->s_desc_size : EXT2_MIN_DESC_SIZE)
+
#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group)
#define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group)
#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
@@ -227,7 +235,7 @@
#define EXT2_DESC_PER_BLOCK(s) (EXT2_SB(s)->s_desc_per_block)
#define EXT2_DESC_PER_BLOCK_BITS(s) (EXT2_SB(s)->s_desc_per_block_bits)
#else
-#define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
+#define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_DESC_SIZE(s))
#endif
/*
@@ -319,9 +327,6 @@
struct {
__u32 h_i_translator;
} hurd1;
- struct {
- __u32 m_i_reserved1;
- } masix1;
} osd1; /* OS dependent 1 */
__u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
__u32 i_generation; /* File version (for NFS) */
@@ -344,12 +349,6 @@
__u16 h_i_gid_high;
__u32 h_i_author;
} hurd2;
- struct {
- __u8 m_i_frag; /* Fragment number */
- __u8 m_i_fsize; /* Fragment size */
- __u16 m_pad1;
- __u32 m_i_reserved2[2];
- } masix2;
} osd2; /* OS dependent 2 */
};
@@ -375,9 +374,6 @@
struct {
__u32 h_i_translator;
} hurd1;
- struct {
- __u32 m_i_reserved1;
- } masix1;
} osd1; /* OS dependent 1 */
__u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
__u32 i_generation; /* File version (for NFS) */
@@ -400,12 +396,6 @@
__u16 h_i_gid_high;
__u32 h_i_author;
} hurd2;
- struct {
- __u8 m_i_frag; /* Fragment number */
- __u8 m_i_fsize; /* Fragment size */
- __u16 m_pad1;
- __u32 m_i_reserved2[2];
- } masix2;
} osd2; /* OS dependent 2 */
__u16 i_extra_isize;
__u16 i_pad1;
@@ -437,30 +427,13 @@
#define i_gid_high osd2.hurd2.h_i_gid_high
#define i_author osd2.hurd2.h_i_author
-#else
-#if defined(__masix__)
-
-#define i_reserved1 osd1.masix1.m_i_reserved1
-#define i_frag osd2.masix2.m_i_frag
-#define i_fsize osd2.masix2.m_i_fsize
-#define i_reserved2 osd2.masix2.m_i_reserved2
-
-#endif /* __masix__ */
#endif /* __GNU__ */
#endif /* defined(__KERNEL__) || defined(__linux__) */
-#if defined(__masix__)
-#define inode_uid(inode) ((inode).i_uid)
-#define inode_gid(inode) ((inode).i_gid)
-#define ext2fs_set_i_uid_high(inode,x) (x)
-#define ext2fs_set_i_gid_high(inode,x) (x)
-
-#else
#define inode_uid(inode) ((inode).i_uid | (inode).osd2.linux2.l_i_uid_high << 16)
#define inode_gid(inode) ((inode).i_gid | (inode).osd2.linux2.l_i_gid_high << 16)
#define ext2fs_set_i_uid_high(inode,x) ((inode).osd2.linux2.l_i_uid_high = (x))
#define ext2fs_set_i_gid_high(inode,x) ((inode).osd2.linux2.l_i_gid_high = (x))
-#endif
/*
* File system states
@@ -598,7 +571,7 @@
*/
#define EXT2_OS_LINUX 0
#define EXT2_OS_HURD 1
-#define EXT2_OS_MASIX 2
+#define EXT2_OBSO_OS_MASIX 2
#define EXT2_OS_FREEBSD 3
#define EXT2_OS_LITES 4
@@ -653,12 +626,14 @@
#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040
#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
+#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
#define EXT2_FEATURE_COMPAT_SUPP 0
#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE)
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
+ EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \
EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
/*
diff --git a/lib/ext2fs/ext2_io.h b/lib/ext2fs/ext2_io.h
index eada278..c236095 100644
--- a/lib/ext2fs/ext2_io.h
+++ b/lib/ext2fs/ext2_io.h
@@ -26,6 +26,7 @@
typedef struct struct_io_manager *io_manager;
typedef struct struct_io_channel *io_channel;
+typedef struct struct_io_stats *io_stats;
#define CHANNEL_FLAGS_WRITETHROUGH 0x01
@@ -55,6 +56,13 @@
void *app_data;
};
+struct struct_io_stats {
+ int num_fields;
+ int reserved;
+ unsigned long long bytes_read;
+ unsigned long long bytes_written;
+};
+
struct struct_io_manager {
errcode_t magic;
const char *name;
@@ -70,7 +78,12 @@
int count, const void *data);
errcode_t (*set_option)(io_channel channel, const char *option,
const char *arg);
- int reserved[14];
+ errcode_t (*get_stats)(io_channel channel, io_stats *io_stats);
+ errcode_t (*read_blk64)(io_channel channel, unsigned long long block,
+ int count, void *data);
+ errcode_t (*write_blk64)(io_channel channel, unsigned long long block,
+ int count, const void *data);
+ int reserved[16];
};
#define IO_FLAG_RW 0x0001
@@ -82,7 +95,9 @@
#define io_channel_close(c) ((c)->manager->close((c)))
#define io_channel_set_blksize(c,s) ((c)->manager->set_blksize((c),s))
#define io_channel_read_blk(c,b,n,d) ((c)->manager->read_blk((c),b,n,d))
+#define io_channel_read_blk64(c,b,n,d) ((c)->manager->read_blk64((c),b,n,d))
#define io_channel_write_blk(c,b,n,d) ((c)->manager->write_blk((c),b,n,d))
+#define io_channel_write_blk64(c,b,n,d) ((c)->manager->write_blk64((c),b,n,d))
#define io_channel_flush(c) ((c)->manager->flush((c)))
#define io_channel_bumpcount(c) ((c)->refcount++)
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index d098961..1a7cb86 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -30,15 +30,6 @@
#endif
/*
- * Build in support for byte-swapping filesystems if we the feature
- * has been configured or if we're being built on a CPU architecture
- * with a non-native byte order.
- */
-#if defined(ENABLE_SWAPFS) || defined(WORDS_BIGENDIAN)
-#define EXT2FS_ENABLE_SWAPFS
-#endif
-
-/*
* Where the master copy of the superblock is located, and how big
* superblocks are supposed to be. We define SUPERBLOCK_SIZE because
* the size of the superblock structure is not necessarily trustworthy
@@ -74,6 +65,7 @@
typedef __u32 ext2_ino_t;
typedef __u32 blk_t;
+typedef __u64 blk64_t;
typedef __u32 dgrp_t;
typedef __u32 ext2_off_t;
typedef __s64 e2_blkcnt_t;
@@ -83,10 +75,12 @@
#include "com_err.h"
#include "ext2_io.h"
#include "ext2_err.h"
+#include "ext2_ext_attr.h"
#else
#include <et/com_err.h>
#include <ext2fs/ext2_io.h>
#include <ext2fs/ext2_err.h>
+#include <ext2fs/ext2_ext_attr.h>
#endif
/*
@@ -100,17 +94,6 @@
typedef struct struct_ext2_filsys *ext2_filsys;
-struct ext2fs_struct_generic_bitmap {
- errcode_t magic;
- ext2_filsys fs;
- __u32 start, end;
- __u32 real_end;
- char * description;
- char * bitmap;
- errcode_t base_error_code;
- __u32 reserved[7];
-};
-
#define EXT2FS_MARK_ERROR 0
#define EXT2FS_UNMARK_ERROR 1
#define EXT2FS_TEST_ERROR 2
@@ -279,6 +262,9 @@
* BLOCK_FLAG_DATA_ONLY indicates that the iterator function should be
* called for data blocks only.
*
+ * BLOCK_FLAG_READ_ONLY is a promise by the caller that it will not
+ * modify returned block number.
+ *
* BLOCK_FLAG_NO_LARGE is for internal use only. It informs
* ext2fs_block_iterate2 that large files won't be accepted.
*/
@@ -286,6 +272,7 @@
#define BLOCK_FLAG_HOLE 1
#define BLOCK_FLAG_DEPTH_TRAVERSE 2
#define BLOCK_FLAG_DATA_ONLY 4
+#define BLOCK_FLAG_READ_ONLY 8
#define BLOCK_FLAG_NO_LARGE 0x1000
@@ -306,6 +293,65 @@
#endif
/*
+ * Generic (non-filesystem layout specific) extents structure
+ */
+
+#define EXT2_EXTENT_FLAGS_LEAF 0x0001
+#define EXT2_EXTENT_FLAGS_UNINIT 0x0002
+#define EXT2_EXTENT_FLAGS_SECOND_VISIT 0x0004
+
+struct ext2fs_extent {
+ blk64_t e_pblk; /* first physical block */
+ blk64_t e_lblk; /* first logical block extent covers */
+ __u32 e_len; /* number of blocks covered by extent */
+ __u32 e_flags; /* extent flags */
+};
+
+typedef struct ext2_extent_handle *ext2_extent_handle_t;
+typedef struct ext2_extent_path *ext2_extent_path_t;
+
+/*
+ * Flags used by ext2fs_extent_get()
+ */
+#define EXT2_EXTENT_CURRENT 0x0000
+#define EXT2_EXTENT_MOVE_MASK 0x000F
+#define EXT2_EXTENT_ROOT 0x0001
+#define EXT2_EXTENT_LAST_LEAF 0x0002
+#define EXT2_EXTENT_FIRST_SIB 0x0003
+#define EXT2_EXTENT_LAST_SIB 0x0004
+#define EXT2_EXTENT_NEXT_SIB 0x0005
+#define EXT2_EXTENT_PREV_SIB 0x0006
+#define EXT2_EXTENT_NEXT_LEAF 0x0007
+#define EXT2_EXTENT_PREV_LEAF 0x0008
+#define EXT2_EXTENT_NEXT 0x0009
+#define EXT2_EXTENT_PREV 0x000A
+#define EXT2_EXTENT_UP 0x000B
+#define EXT2_EXTENT_DOWN 0x000C
+#define EXT2_EXTENT_DOWN_AND_LAST 0x000D
+
+/*
+ * Flags used by ext2fs_extent_insert()
+ */
+
+#define EXT2_EXTENT_INSERT_AFTER 0x0001
+
+/*
+ * Data structure returned by ext2fs_extent_get_info()
+ */
+struct ext2_extent_info {
+ int curr_entry;
+ int curr_level;
+ int num_entries;
+ int max_entries;
+ int max_depth;
+ int bytes_avail;
+ blk64_t max_lblk;
+ blk64_t max_pblk;
+ __u32 max_len;
+ __u32 max_uninit_len;
+};
+
+/*
* Flags for directory block reading and writing functions
*/
#define EXT2_DIRBLOCK_V2_STRUCT 0x0001
@@ -411,6 +457,11 @@
#define BMAP_SET 0x0002
/*
+ * Returned flags from ext2fs_bmap
+ */
+#define BMAP_RET_UNINIT 0x0001
+
+/*
* Flags for imager.c functions
*/
#define IMAGER_FLAG_INODEMAP 1
@@ -427,7 +478,7 @@
/*
* For ext2 compression support
*/
-#define EXT2FS_COMPRESSED_BLKADDR ((blk_t) 0xffffffff)
+#define EXT2FS_COMPRESSED_BLKADDR ((blk_t) -1)
#define HOLE_BLKADDR(_b) ((_b) == 0 || (_b) == EXT2FS_COMPRESSED_BLKADDR)
/*
@@ -453,15 +504,21 @@
EXT2_FEATURE_INCOMPAT_COMPRESSION|\
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
EXT2_FEATURE_INCOMPAT_META_BG|\
- EXT3_FEATURE_INCOMPAT_RECOVER)
+ EXT3_FEATURE_INCOMPAT_RECOVER|\
+ EXT3_FEATURE_INCOMPAT_EXTENTS|\
+ EXT4_FEATURE_INCOMPAT_FLEX_BG)
#else
#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
EXT2_FEATURE_INCOMPAT_META_BG|\
- EXT3_FEATURE_INCOMPAT_RECOVER)
+ EXT3_FEATURE_INCOMPAT_RECOVER|\
+ EXT3_FEATURE_INCOMPAT_EXTENTS|\
+ EXT4_FEATURE_INCOMPAT_FLEX_BG)
#endif
#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE)
+ EXT2_FEATURE_RO_COMPAT_LARGE_FILE|\
+ EXT4_FEATURE_RO_COMPAT_DIR_NLINK|\
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM)
/*
* These features are only allowed if EXT2_FLAG_SOFTSUPP_FEATURES is passed
@@ -470,7 +527,6 @@
#define EXT2_LIB_SOFTSUPP_INCOMPAT (EXT3_FEATURE_INCOMPAT_EXTENTS)
#define EXT2_LIB_SOFTSUPP_RO_COMPAT (EXT4_FEATURE_RO_COMPAT_HUGE_FILE|\
EXT4_FEATURE_RO_COMPAT_GDT_CSUM|\
- EXT4_FEATURE_RO_COMPAT_DIR_NLINK|\
EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE)
/*
@@ -552,15 +608,14 @@
ext2_badblocks_list bb_list);
/* bitmaps.c */
+extern void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap);
+extern void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap);
+extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
+ ext2fs_generic_bitmap *dest);
extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs);
extern errcode_t ext2fs_write_block_bitmap (ext2_filsys fs);
extern errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs);
extern errcode_t ext2fs_read_block_bitmap(ext2_filsys fs);
-extern errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
- __u32 end,
- __u32 real_end,
- const char *descr,
- ext2fs_generic_bitmap *ret);
extern errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
const char *descr,
ext2fs_block_bitmap *ret);
@@ -575,6 +630,27 @@
extern void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap);
extern errcode_t ext2fs_read_bitmaps(ext2_filsys fs);
extern errcode_t ext2fs_write_bitmaps(ext2_filsys fs);
+extern errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
+ ext2fs_inode_bitmap bmap);
+extern errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
+ ext2fs_block_bitmap bmap);
+extern errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
+ ext2fs_block_bitmap bm2);
+extern errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
+ ext2fs_inode_bitmap bm2);
+extern errcode_t ext2fs_set_inode_bitmap_range(ext2fs_inode_bitmap bmap,
+ ext2_ino_t start, unsigned int num,
+ void *in);
+extern errcode_t ext2fs_get_inode_bitmap_range(ext2fs_inode_bitmap bmap,
+ ext2_ino_t start, unsigned int num,
+ void *out);
+extern errcode_t ext2fs_set_block_bitmap_range(ext2fs_block_bitmap bmap,
+ blk_t start, unsigned int num,
+ void *in);
+extern errcode_t ext2fs_get_block_bitmap_range(ext2fs_block_bitmap bmap,
+ blk_t start, unsigned int num,
+ void *out);
+
/* block.c */
extern errcode_t ext2fs_block_iterate(ext2_filsys fs,
@@ -603,7 +679,10 @@
struct ext2_inode *inode,
char *block_buf, int bmap_flags,
blk_t block, blk_t *phys_blk);
-
+extern errcode_t ext2fs_bmap2(ext2_filsys fs, ext2_ino_t ino,
+ struct ext2_inode *inode,
+ char *block_buf, int bmap_flags, blk64_t block,
+ int *ret_flags, blk64_t *phys_blk);
#if 0
/* bmove.c */
@@ -628,11 +707,10 @@
int *ret_meta_bg);
extern void ext2fs_update_dynamic_rev(ext2_filsys fs);
-/* cmp_bitmaps.c */
-extern errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
- ext2fs_block_bitmap bm2);
-extern errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
- ext2fs_inode_bitmap bm2);
+/* csum.c */
+extern void ext2fs_group_desc_csum_set(ext2_filsys fs, dgrp_t group);
+extern int ext2fs_group_desc_csum_verify(ext2_filsys fs, dgrp_t group);
+extern errcode_t ext2fs_set_gdt_csum(ext2_filsys fs);
/* dblist.c */
@@ -718,6 +796,8 @@
extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir);
/* ext_attr.c */
+extern __u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry,
+ void *data);
extern errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf);
extern errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block,
void *buf);
@@ -725,6 +805,23 @@
char *block_buf,
int adjust, __u32 *newcount);
+/* extent.c */
+extern errcode_t ext2fs_extent_header_verify(void *ptr, int size);
+extern errcode_t ext2fs_extent_open(ext2_filsys fs, ext2_ino_t ino,
+ ext2_extent_handle_t *handle);
+extern void ext2fs_extent_free(ext2_extent_handle_t handle);
+extern errcode_t ext2fs_extent_get(ext2_extent_handle_t handle,
+ int flags, struct ext2fs_extent *extent);
+extern errcode_t ext2fs_extent_replace(ext2_extent_handle_t handle, int flags,
+ struct ext2fs_extent *extent);
+extern errcode_t ext2fs_extent_insert(ext2_extent_handle_t handle, int flags,
+ struct ext2fs_extent *extent);
+extern errcode_t ext2fs_extent_delete(ext2_extent_handle_t handle, int flags);
+extern errcode_t ext2fs_extent_get_info(ext2_extent_handle_t handle,
+ struct ext2_extent_info *info);
+extern errcode_t ext2fs_extent_goto(ext2_extent_handle_t handle,
+ blk64_t blk);
+
/* fileio.c */
extern errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
@@ -754,13 +851,47 @@
/* freefs.c */
extern void ext2fs_free(ext2_filsys fs);
-extern void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap);
-extern void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap);
-extern void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap);
extern void ext2fs_free_dblist(ext2_dblist dblist);
extern void ext2fs_badblocks_list_free(ext2_badblocks_list bb);
extern void ext2fs_u32_list_free(ext2_u32_list bb);
+/* gen_bitmap.c */
+extern void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap);
+extern errcode_t ext2fs_make_generic_bitmap(errcode_t magic, ext2_filsys fs,
+ __u32 start, __u32 end,
+ __u32 real_end,
+ const char *descr, char *init_map,
+ ext2fs_generic_bitmap *ret);
+extern errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
+ __u32 end,
+ __u32 real_end,
+ const char *descr,
+ ext2fs_generic_bitmap *ret);
+extern errcode_t ext2fs_copy_generic_bitmap(ext2fs_generic_bitmap src,
+ ext2fs_generic_bitmap *dest);
+extern void ext2fs_clear_generic_bitmap(ext2fs_generic_bitmap bitmap);
+extern errcode_t ext2fs_fudge_generic_bitmap_end(ext2fs_inode_bitmap bitmap,
+ errcode_t magic,
+ errcode_t neq,
+ ext2_ino_t end,
+ ext2_ino_t *oend);
+extern void ext2fs_set_generic_bitmap_padding(ext2fs_generic_bitmap map);
+extern errcode_t ext2fs_resize_generic_bitmap(errcode_t magic,
+ __u32 new_end,
+ __u32 new_real_end,
+ ext2fs_generic_bitmap bmap);
+extern errcode_t ext2fs_compare_generic_bitmap(errcode_t magic, errcode_t neq,
+ ext2fs_generic_bitmap bm1,
+ ext2fs_generic_bitmap bm2);
+extern errcode_t ext2fs_get_generic_bitmap_range(ext2fs_generic_bitmap bmap,
+ errcode_t magic,
+ __u32 start, __u32 num,
+ void *out);
+extern errcode_t ext2fs_set_generic_bitmap_range(ext2fs_generic_bitmap bmap,
+ errcode_t magic,
+ __u32 start, __u32 num,
+ void *in);
+
/* getsize.c */
extern errcode_t ext2fs_get_device_size(const char *file, int blocksize,
blk_t *retblocks);
@@ -931,20 +1062,13 @@
/* res_gdt.c */
extern errcode_t ext2fs_create_resize_inode(ext2_filsys fs);
-/* rs_bitmap.c */
-extern errcode_t ext2fs_resize_generic_bitmap(__u32 new_end,
- __u32 new_real_end,
- ext2fs_generic_bitmap bmap);
-extern errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
- ext2fs_inode_bitmap bmap);
-extern errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
- ext2fs_block_bitmap bmap);
-extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
- ext2fs_generic_bitmap *dest);
-
/* swapfs.c */
extern void ext2fs_swap_ext_attr(char *to, char *from, int bufsize,
int has_header);
+extern void ext2fs_swap_ext_attr_header(struct ext2_ext_attr_header *to_header,
+ struct ext2_ext_attr_header *from_hdr);
+extern void ext2fs_swap_ext_attr_entry(struct ext2_ext_attr_entry *to_entry,
+ struct ext2_ext_attr_entry *from_entry);
extern void ext2fs_swap_super(struct ext2_super_block * super);
extern void ext2fs_swap_group_desc(struct ext2_group_desc *gdp);
extern void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t,
diff --git a/lib/ext2fs/ext3_extents.h b/lib/ext2fs/ext3_extents.h
index c4178c9..ba980e4 100644
--- a/lib/ext2fs/ext3_extents.h
+++ b/lib/ext2fs/ext3_extents.h
@@ -126,6 +126,26 @@
#define EXT_MAX_BLOCK 0xffffffff
#define EXT_CACHE_MARK 0xffff
+/*
+ * EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an
+ * initialized extent. This is 2^15 and not (2^16 - 1), since we use the
+ * MSB of ee_len field in the extent datastructure to signify if this
+ * particular extent is an initialized extent or an uninitialized (i.e.
+ * preallocated).
+ * EXT_UNINIT_MAX_LEN is the maximum number of blocks we can have in an
+ * uninitialized extent.
+ * If ee_len is <= 0x8000, it is an initialized extent. Otherwise, it is an
+ * uninitialized one. In other words, if MSB of ee_len is set, it is an
+ * uninitialized extent with only one special scenario when ee_len = 0x8000.
+ * In this case we can not have an uninitialized extent of zero length and
+ * thus we make it as a special case of initialized extent with 0x8000 length.
+ * This way we get better extent-to-group alignment for initialized extents.
+ * Hence, the maximum number of blocks we can have in an *initialized*
+ * extent is 2^15 (32768) and in an *uninitialized* extent is 2^15-1 (32767).
+ */
+#define EXT_INIT_MAX_LEN (1UL << 15)
+#define EXT_UNINIT_MAX_LEN (EXT_INIT_MAX_LEN - 1)
+
#define EXT_FIRST_EXTENT(__hdr__) \
((struct ext3_extent *) (((char *) (__hdr__)) + \
diff --git a/lib/ext2fs/ext_attr.c b/lib/ext2fs/ext_attr.c
index 08211c3..3d208ec 100644
--- a/lib/ext2fs/ext_attr.c
+++ b/lib/ext2fs/ext_attr.c
@@ -23,6 +23,43 @@
#include "ext2fs.h"
+#define NAME_HASH_SHIFT 5
+#define VALUE_HASH_SHIFT 16
+
+/*
+ * ext2_xattr_hash_entry()
+ *
+ * Compute the hash of an extended attribute.
+ */
+__u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry, void *data)
+{
+ __u32 hash = 0;
+ char *name = ((char *) entry) + sizeof(struct ext2_ext_attr_entry);
+ int n;
+
+ for (n = 0; n < entry->e_name_len; n++) {
+ hash = (hash << NAME_HASH_SHIFT) ^
+ (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
+ *name++;
+ }
+
+ /* The hash needs to be calculated on the data in little-endian. */
+ if (entry->e_value_block == 0 && entry->e_value_size != 0) {
+ __u32 *value = (__u32 *)data;
+ for (n = (entry->e_value_size + EXT2_EXT_ATTR_ROUND) >>
+ EXT2_EXT_ATTR_PAD_BITS; n; n--) {
+ hash = (hash << VALUE_HASH_SHIFT) ^
+ (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
+ ext2fs_le32_to_cpu(*value++);
+ }
+ }
+
+ return hash;
+}
+
+#undef NAME_HASH_SHIFT
+#undef VALUE_HASH_SHIFT
+
errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf)
{
errcode_t retval;
@@ -30,10 +67,8 @@
retval = io_channel_read_blk(fs->io, block, 1, buf);
if (retval)
return retval;
-#ifdef EXT2FS_ENABLE_SWAPFS
- if ((fs->flags & (EXT2_FLAG_SWAP_BYTES|
- EXT2_FLAG_SWAP_BYTES_READ)) != 0)
- ext2fs_swap_ext_attr(buf, buf, fs->blocksize, 1);
+#ifdef WORDS_BIGENDIAN
+ ext2fs_swap_ext_attr(buf, buf, fs->blocksize, 1);
#endif
return 0;
}
@@ -44,17 +79,15 @@
char *write_buf;
char *buf = NULL;
-#ifdef EXT2FS_ENABLE_SWAPFS
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) {
- retval = ext2fs_get_mem(fs->blocksize, &buf);
- if (retval)
- return retval;
- write_buf = buf;
- ext2fs_swap_ext_attr(buf, inbuf, fs->blocksize, 1);
- } else
+#ifdef WORDS_BIGENDIAN
+ retval = ext2fs_get_mem(fs->blocksize, &buf);
+ if (retval)
+ return retval;
+ write_buf = buf;
+ ext2fs_swap_ext_attr(buf, inbuf, fs->blocksize, 1);
+#else
+ write_buf = (char *) inbuf;
#endif
- write_buf = (char *) inbuf;
retval = io_channel_write_blk(fs->io, block, 1, write_buf);
if (buf)
ext2fs_free_mem(&buf);
diff --git a/lib/ext2fs/extent.c b/lib/ext2fs/extent.c
new file mode 100644
index 0000000..e7733c5
--- /dev/null
+++ b/lib/ext2fs/extent.c
@@ -0,0 +1,1149 @@
+/*
+ * extent.c --- routines to implement extents support
+ *
+ * Copyright (C) 2007 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+#include "e2image.h"
+#include "ss/ss.h"
+
+/*
+ * Definitions to be dropped in lib/ext2fs/ext2fs.h
+ */
+
+/*
+ * Private definitions
+ */
+
+struct extent_path {
+ char *buf;
+ int entries;
+ int max_entries;
+ int left;
+ int visit_num;
+ int flags;
+ blk64_t end_blk;
+ void *curr;
+};
+
+
+struct ext2_extent_handle {
+ errcode_t magic;
+ ext2_filsys fs;
+ ext2_ino_t ino;
+ struct ext2_inode *inode;
+ int type;
+ int level;
+ int max_depth;
+ struct extent_path *path;
+};
+
+struct ext2_extent_path {
+ errcode_t magic;
+ int leaf_height;
+ blk64_t lblk;
+};
+
+/*
+ * Useful Debugging stuff
+ */
+
+#ifdef DEBUG
+static void dbg_show_header(struct ext3_extent_header *eh)
+{
+ printf("header: magic=%x entries=%u max=%u depth=%u generation=%u\n",
+ eh->eh_magic, eh->eh_entries, eh->eh_max, eh->eh_depth,
+ eh->eh_generation);
+}
+
+static void dbg_show_index(struct ext3_extent_idx *ix)
+{
+ printf("index: block=%u leaf=%u leaf_hi=%u unused=%u\n",
+ ix->ei_block, ix->ei_leaf, ix->ei_leaf_hi, ix->ei_unused);
+}
+
+static void dbg_show_extent(struct ext3_extent *ex)
+{
+ printf("extent: block=%u-%u len=%u start=%u start_hi=%u\n",
+ ex->ee_block, ex->ee_block + ex->ee_len - 1,
+ ex->ee_len, ex->ee_start, ex->ee_start_hi);
+}
+
+static void dbg_print_extent(char *desc, struct ext2fs_extent *extent)
+{
+ if (desc)
+ printf("%s: ", desc);
+ printf("extent: lblk %llu--%llu, len %lu, pblk %llu, flags: ",
+ extent->e_lblk, extent->e_lblk + extent->e_len - 1,
+ extent->e_len, extent->e_pblk);
+ if (extent->e_flags & EXT2_EXTENT_FLAGS_LEAF)
+ fputs("LEAF ", stdout);
+ if (extent->e_flags & EXT2_EXTENT_FLAGS_UNINIT)
+ fputs("UNINIT ", stdout);
+ if (extent->e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT)
+ fputs("2ND_VISIT ", stdout);
+ if (!extent->e_flags)
+ fputs("(none)", stdout);
+ fputc('\n', stdout);
+
+}
+
+#define dbg_printf(fmt, args...) printf(fmt, ## args)
+#else
+#define dbg_show_header(eh) do { } while (0)
+#define dbg_show_index(ix) do { } while (0)
+#define dbg_show_extent(ex) do { } while (0)
+#define dbg_print_extent(desc, ex) do { } while (0)
+#define dbg_printf(fmt, args...) do { } while (0)
+#endif
+
+/*
+ * Verify the extent header as being sane
+ */
+errcode_t ext2fs_extent_header_verify(void *ptr, int size)
+{
+ int eh_max, entry_size;
+ struct ext3_extent_header *eh = ptr;
+
+ dbg_show_header(eh);
+ if (ext2fs_le16_to_cpu(eh->eh_magic) != EXT3_EXT_MAGIC)
+ return EXT2_ET_EXTENT_HEADER_BAD;
+ if (ext2fs_le16_to_cpu(eh->eh_entries) > ext2fs_le16_to_cpu(eh->eh_max))
+ return EXT2_ET_EXTENT_HEADER_BAD;
+ if (eh->eh_depth == 0)
+ entry_size = sizeof(struct ext3_extent);
+ else
+ entry_size = sizeof(struct ext3_extent_idx);
+
+ eh_max = (size - sizeof(*eh)) / entry_size;
+ /* Allow two extent-sized items at the end of the block, for
+ * ext4_extent_tail with checksum in the future. */
+ if ((ext2fs_le16_to_cpu(eh->eh_max) > eh_max) ||
+ (ext2fs_le16_to_cpu(eh->eh_max) < (eh_max - 2)))
+ return EXT2_ET_EXTENT_HEADER_BAD;
+
+ return 0;
+}
+
+
+/*
+ * Begin functions to handle an inode's extent information
+ */
+extern void ext2fs_extent_free(ext2_extent_handle_t handle)
+{
+ int i;
+
+ if (!handle)
+ return;
+
+ if (handle->inode)
+ ext2fs_free_mem(&handle->inode);
+ if (handle->path) {
+ for (i=1; i < handle->max_depth; i++) {
+ if (handle->path[i].buf)
+ ext2fs_free_mem(&handle->path[i].buf);
+ }
+ ext2fs_free_mem(&handle->path);
+ }
+ ext2fs_free_mem(&handle);
+}
+
+extern errcode_t ext2fs_extent_open(ext2_filsys fs, ext2_ino_t ino,
+ ext2_extent_handle_t *ret_handle)
+{
+ struct ext2_extent_handle *handle;
+ errcode_t retval;
+ int isize = EXT2_INODE_SIZE(fs->super);
+ struct ext3_extent_header *eh;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if ((ino == 0) || (ino > fs->super->s_inodes_count))
+ return EXT2_ET_BAD_INODE_NUM;
+
+ retval = ext2fs_get_mem(sizeof(struct ext2_extent_handle), &handle);
+ if (retval)
+ return retval;
+ memset(handle, 0, sizeof(struct ext2_extent_handle));
+
+ retval = ext2fs_get_mem(isize, &handle->inode);
+ if (retval)
+ goto errout;
+
+ handle->ino = ino;
+ handle->fs = fs;
+
+ retval = ext2fs_read_inode_full(fs, ino, handle->inode, isize);
+ if (retval)
+ goto errout;
+
+ if (!(handle->inode->i_flags & EXT4_EXTENTS_FL))
+ return EXT2_ET_INODE_NOT_EXTENT;
+
+ eh = (struct ext3_extent_header *) &handle->inode->i_block[0];
+
+ retval = ext2fs_extent_header_verify(eh, sizeof(handle->inode->i_block));
+ if (retval)
+ return (retval);
+
+ handle->max_depth = ext2fs_le16_to_cpu(eh->eh_depth);
+ handle->type = ext2fs_le16_to_cpu(eh->eh_magic);
+
+ retval = ext2fs_get_mem(((handle->max_depth+1) *
+ sizeof(struct extent_path)),
+ &handle->path);
+ memset(handle->path, 0,
+ (handle->max_depth+1) * sizeof(struct extent_path));
+ handle->path[0].buf = (char *) handle->inode->i_block;
+
+ handle->path[0].left = handle->path[0].entries =
+ ext2fs_le16_to_cpu(eh->eh_entries);
+ handle->path[0].max_entries = ext2fs_le16_to_cpu(eh->eh_max);
+ handle->path[0].curr = 0;
+ handle->path[0].end_blk =
+ ((((__u64) handle->inode->i_size_high << 32) +
+ handle->inode->i_size + (fs->blocksize - 1))
+ >> EXT2_BLOCK_SIZE_BITS(fs->super));
+ handle->path[0].visit_num = 1;
+ handle->level = 0;
+ handle->magic = EXT2_ET_MAGIC_EXTENT_HANDLE;
+
+ *ret_handle = handle;
+ return 0;
+
+errout:
+ ext2fs_extent_free(handle);
+ return retval;
+}
+
+/*
+ * This function is responsible for (optionally) moving through the
+ * extent tree and then returning the current extent
+ */
+errcode_t ext2fs_extent_get(ext2_extent_handle_t handle,
+ int flags, struct ext2fs_extent *extent)
+{
+ struct extent_path *path, *newpath;
+ struct ext3_extent_header *eh;
+ struct ext3_extent_idx *ix = 0;
+ struct ext3_extent *ex;
+ errcode_t retval;
+ blk_t blk;
+ blk64_t end_blk;
+ int orig_op, op;
+
+ EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
+
+ if (!handle->path)
+ return EXT2_ET_NO_CURRENT_NODE;
+
+ orig_op = op = flags & EXT2_EXTENT_MOVE_MASK;
+
+retry:
+ path = handle->path + handle->level;
+ if ((orig_op == EXT2_EXTENT_NEXT) ||
+ (orig_op == EXT2_EXTENT_NEXT_LEAF)) {
+ if (handle->level < handle->max_depth) {
+ /* interior node */
+ if (path->visit_num == 0) {
+ path->visit_num++;
+ op = EXT2_EXTENT_DOWN;
+ } else if (path->left > 0)
+ op = EXT2_EXTENT_NEXT_SIB;
+ else if (handle->level > 0)
+ op = EXT2_EXTENT_UP;
+ else
+ return EXT2_ET_EXTENT_NO_NEXT;
+ } else {
+ /* leaf node */
+ if (path->left > 0)
+ op = EXT2_EXTENT_NEXT_SIB;
+ else if (handle->level > 0)
+ op = EXT2_EXTENT_UP;
+ else
+ return EXT2_ET_EXTENT_NO_NEXT;
+ }
+ if (op != EXT2_EXTENT_NEXT_SIB) {
+ dbg_printf("<<<< OP = %s\n",
+ (op == EXT2_EXTENT_DOWN) ? "down" :
+ ((op == EXT2_EXTENT_UP) ? "up" : "unknown"));
+ }
+ }
+
+ if ((orig_op == EXT2_EXTENT_PREV) ||
+ (orig_op == EXT2_EXTENT_PREV_LEAF)) {
+ if (handle->level < handle->max_depth) {
+ /* interior node */
+ if (path->visit_num > 0 ) {
+ /* path->visit_num = 0; */
+ op = EXT2_EXTENT_DOWN_AND_LAST;
+ } else if (path->left < path->entries-1)
+ op = EXT2_EXTENT_PREV_SIB;
+ else if (handle->level > 0)
+ op = EXT2_EXTENT_UP;
+ else
+ return EXT2_ET_EXTENT_NO_PREV;
+ } else {
+ /* leaf node */
+ if (path->left < path->entries-1)
+ op = EXT2_EXTENT_PREV_SIB;
+ else if (handle->level > 0)
+ op = EXT2_EXTENT_UP;
+ else
+ return EXT2_ET_EXTENT_NO_PREV;
+ }
+ if (op != EXT2_EXTENT_PREV_SIB) {
+ dbg_printf("<<<< OP = %s\n",
+ (op == EXT2_EXTENT_DOWN_AND_LAST) ? "down/last" :
+ ((op == EXT2_EXTENT_UP) ? "up" : "unknown"));
+ }
+ }
+
+ if (orig_op == EXT2_EXTENT_LAST_LEAF) {
+ if ((handle->level < handle->max_depth) &&
+ (path->left == 0))
+ op = EXT2_EXTENT_DOWN;
+ else
+ op = EXT2_EXTENT_LAST_SIB;
+ dbg_printf("<<<< OP = %s\n",
+ (op == EXT2_EXTENT_DOWN) ? "down" : "last_sib");
+ }
+
+ switch (op) {
+ case EXT2_EXTENT_CURRENT:
+ ix = path->curr;
+ break;
+ case EXT2_EXTENT_ROOT:
+ handle->level = 0;
+ path = handle->path + handle->level;
+ case EXT2_EXTENT_FIRST_SIB:
+ path->left = path->entries;
+ path->curr = 0;
+ case EXT2_EXTENT_NEXT_SIB:
+ if (path->left <= 0)
+ return EXT2_ET_EXTENT_NO_NEXT;
+ if (path->curr) {
+ ix = path->curr;
+ ix++;
+ } else {
+ eh = (struct ext3_extent_header *) path->buf;
+ ix = EXT_FIRST_INDEX(eh);
+ }
+ path->left--;
+ path->curr = ix;
+ path->visit_num = 0;
+ break;
+ case EXT2_EXTENT_PREV_SIB:
+ if (!path->curr ||
+ path->left+1 >= path->entries)
+ return EXT2_ET_EXTENT_NO_PREV;
+ ix = path->curr;
+ ix--;
+ path->curr = ix;
+ path->left++;
+ if (handle->level < handle->max_depth)
+ path->visit_num = 1;
+ break;
+ case EXT2_EXTENT_LAST_SIB:
+ eh = (struct ext3_extent_header *) path->buf;
+ path->curr = EXT_LAST_EXTENT(eh);
+ ix = path->curr;
+ path->left = 0;
+ path->visit_num = 0;
+ break;
+ case EXT2_EXTENT_UP:
+ if (handle->level <= 0)
+ return EXT2_ET_EXTENT_NO_UP;
+ handle->level--;
+ path--;
+ ix = path->curr;
+ if ((orig_op == EXT2_EXTENT_PREV) ||
+ (orig_op == EXT2_EXTENT_PREV_LEAF))
+ path->visit_num = 0;
+ break;
+ case EXT2_EXTENT_DOWN:
+ case EXT2_EXTENT_DOWN_AND_LAST:
+ if (!path->curr ||(handle->level >= handle->max_depth))
+ return EXT2_ET_EXTENT_NO_DOWN;
+
+ ix = path->curr;
+ newpath = path + 1;
+ if (!newpath->buf) {
+ retval = ext2fs_get_mem(handle->fs->blocksize,
+ &newpath->buf);
+ if (retval)
+ return retval;
+ }
+ blk = ext2fs_le32_to_cpu(ix->ei_leaf) +
+ ((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32);
+ if ((handle->fs->flags & EXT2_FLAG_IMAGE_FILE) &&
+ (handle->fs->io != handle->fs->image_io))
+ memset(newpath->buf, 0, handle->fs->blocksize);
+ else {
+ retval = io_channel_read_blk(handle->fs->io,
+ blk, 1, newpath->buf);
+ if (retval)
+ return retval;
+ }
+ handle->level++;
+
+ eh = (struct ext3_extent_header *) newpath->buf;
+
+ retval = ext2fs_extent_header_verify(eh, handle->fs->blocksize);
+ if (retval)
+ return retval;
+
+ newpath->left = newpath->entries =
+ ext2fs_le16_to_cpu(eh->eh_entries);
+ newpath->max_entries = ext2fs_le16_to_cpu(eh->eh_max);
+
+ if (path->left > 0) {
+ ix++;
+ newpath->end_blk = ext2fs_le32_to_cpu(ix->ei_block);
+ } else
+ newpath->end_blk = path->end_blk;
+
+ path = newpath;
+ if (op == EXT2_EXTENT_DOWN) {
+ ix = EXT_FIRST_INDEX((struct ext3_extent_header *) eh);
+ path->curr = ix;
+ path->left = path->entries - 1;
+ path->visit_num = 0;
+ } else {
+ ix = EXT_LAST_INDEX((struct ext3_extent_header *) eh);
+ path->curr = ix;
+ path->left = 0;
+ if (handle->level < handle->max_depth)
+ path->visit_num = 1;
+ }
+
+ dbg_printf("Down to level %d/%d, end_blk=%llu\n",
+ handle->level, handle->max_depth,
+ path->end_blk);
+
+ break;
+ default:
+ return EXT2_ET_OP_NOT_SUPPORTED;
+ }
+
+ if (!ix)
+ return EXT2_ET_NO_CURRENT_NODE;
+
+ extent->e_flags = 0;
+ dbg_printf("(Left %d)\n", path->left);
+
+ if (handle->level == handle->max_depth) {
+ ex = (struct ext3_extent *) ix;
+
+ extent->e_pblk = ext2fs_le32_to_cpu(ex->ee_start) +
+ ((__u64) ext2fs_le16_to_cpu(ex->ee_start_hi) << 32);
+ extent->e_lblk = ext2fs_le32_to_cpu(ex->ee_block);
+ extent->e_len = ext2fs_le16_to_cpu(ex->ee_len);
+ extent->e_flags |= EXT2_EXTENT_FLAGS_LEAF;
+ if (extent->e_len > EXT_INIT_MAX_LEN) {
+ extent->e_len -= EXT_INIT_MAX_LEN;
+ extent->e_flags |= EXT2_EXTENT_FLAGS_UNINIT;
+ }
+ } else {
+ extent->e_pblk = ext2fs_le32_to_cpu(ix->ei_leaf) +
+ ((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32);
+ extent->e_lblk = ext2fs_le32_to_cpu(ix->ei_block);
+ if (path->left > 0) {
+ ix++;
+ end_blk = ext2fs_le32_to_cpu(ix->ei_block);
+ } else
+ end_blk = path->end_blk;
+
+ extent->e_len = end_blk - extent->e_lblk;
+ }
+ if (path->visit_num)
+ extent->e_flags |= EXT2_EXTENT_FLAGS_SECOND_VISIT;
+
+ if (((orig_op == EXT2_EXTENT_NEXT_LEAF) ||
+ (orig_op == EXT2_EXTENT_PREV_LEAF)) &&
+ (handle->level != handle->max_depth))
+ goto retry;
+
+ if ((orig_op == EXT2_EXTENT_LAST_LEAF) &&
+ ((handle->level != handle->max_depth) ||
+ (path->left != 0)))
+ goto retry;
+
+ return 0;
+}
+
+static errcode_t update_path(ext2_extent_handle_t handle)
+{
+ blk64_t blk;
+ errcode_t retval;
+ struct ext3_extent_idx *ix;
+
+ if (handle->level == 0) {
+ retval = ext2fs_write_inode_full(handle->fs, handle->ino,
+ handle->inode, EXT2_INODE_SIZE(handle->fs->super));
+ } else {
+ ix = handle->path[handle->level - 1].curr;
+ blk = ext2fs_le32_to_cpu(ix->ei_leaf) +
+ ((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32);
+
+ retval = io_channel_write_blk(handle->fs->io,
+ blk, 1, handle->path[handle->level].buf);
+ }
+ return retval;
+}
+
+#if 0
+errcode_t ext2fs_extent_save_path(ext2_extent_handle_t handle,
+ ext2_extent_path_t *ret_path)
+{
+ ext2_extent_path_t save_path;
+ struct ext2fs_extent extent;
+ struct ext2_extent_info info;
+ errcode_t retval;
+
+ retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent);
+ if (retval)
+ return retval;
+
+ retval = ext2fs_extent_get_info(handle, &info);
+ if (retval)
+ return retval;
+
+ retval = ext2fs_get_mem(sizeof(struct ext2_extent_path), &save_path);
+ if (retval)
+ return retval;
+ memset(save_path, 0, sizeof(struct ext2_extent_path));
+
+ save_path->magic = EXT2_ET_MAGIC_EXTENT_PATH;
+ save_path->leaf_height = info.max_depth - info.curr_level - 1;
+ save_path->lblk = extent.e_lblk;
+
+ *ret_path = save_path;
+ return 0;
+}
+
+errcode_t ext2fs_extent_free_path(ext2_extent_path_t path)
+{
+ EXT2_CHECK_MAGIC(path, EXT2_ET_MAGIC_EXTENT_PATH);
+
+ ext2fs_free_mem(&path);
+ return 0;
+}
+#endif
+
+static errcode_t extent_goto(ext2_extent_handle_t handle,
+ int leaf_level, blk64_t blk)
+{
+ struct ext2fs_extent extent;
+ errcode_t retval;
+
+ retval = ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent);
+ if (retval)
+ return retval;
+
+ dbg_print_extent("root", &extent);
+ while (1) {
+ if (handle->level - leaf_level == handle->max_depth) {
+ if ((blk >= extent.e_lblk) &&
+ (blk < extent.e_lblk + extent.e_len))
+ return 0;
+ if (blk < extent.e_lblk)
+ return EXT2_ET_EXTENT_NOT_FOUND;
+ retval = ext2fs_extent_get(handle,
+ EXT2_EXTENT_NEXT_SIB,
+ &extent);
+ if (retval == EXT2_ET_EXTENT_NO_NEXT)
+ return EXT2_ET_EXTENT_NOT_FOUND;
+ if (retval)
+ return retval;
+ continue;
+ }
+
+ retval = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT_SIB,
+ &extent);
+ if (retval == EXT2_ET_EXTENT_NO_NEXT)
+ goto go_down;
+ if (retval)
+ return retval;
+
+ dbg_print_extent("next", &extent);
+ if (blk == extent.e_lblk)
+ goto go_down;
+ if (blk > extent.e_lblk)
+ continue;
+
+ retval = ext2fs_extent_get(handle, EXT2_EXTENT_PREV_SIB,
+ &extent);
+ if (retval)
+ return retval;
+
+ dbg_print_extent("prev", &extent);
+
+ go_down:
+ retval = ext2fs_extent_get(handle, EXT2_EXTENT_DOWN,
+ &extent);
+ if (retval)
+ return retval;
+
+ dbg_print_extent("down", &extent);
+ }
+}
+
+errcode_t ext2fs_extent_goto(ext2_extent_handle_t handle,
+ blk64_t blk)
+{
+ return extent_goto(handle, 0, blk);
+}
+
+errcode_t ext2fs_extent_replace(ext2_extent_handle_t handle,
+ int flags EXT2FS_ATTR((unused)),
+ struct ext2fs_extent *extent)
+{
+ struct extent_path *path;
+ struct ext3_extent_idx *ix;
+ struct ext3_extent *ex;
+
+ EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
+
+ if (!(handle->fs->flags & EXT2_FLAG_RW))
+ return EXT2_ET_RO_FILSYS;
+
+ if (!handle->path)
+ return EXT2_ET_NO_CURRENT_NODE;
+
+ path = handle->path + handle->level;
+ if (!path->curr)
+ return EXT2_ET_NO_CURRENT_NODE;
+
+ if (handle->level == handle->max_depth) {
+ ex = path->curr;
+
+ ex->ee_block = ext2fs_cpu_to_le32(extent->e_lblk);
+ ex->ee_start = ext2fs_cpu_to_le32(extent->e_pblk & 0xFFFFFFFF);
+ ex->ee_start_hi = ext2fs_cpu_to_le16(extent->e_pblk >> 32);
+ ex->ee_len = ext2fs_cpu_to_le16(extent->e_len);
+ } else {
+ ix = path->curr;
+
+ ix->ei_leaf = ext2fs_cpu_to_le32(extent->e_pblk & 0xFFFFFFFF);
+ ix->ei_leaf_hi = ext2fs_cpu_to_le16(extent->e_pblk >> 32);
+ ix->ei_block = ext2fs_cpu_to_le32(extent->e_lblk);
+ ix->ei_unused = 0;
+ }
+ update_path(handle);
+ return 0;
+}
+
+errcode_t ext2fs_extent_insert(ext2_extent_handle_t handle, int flags,
+ struct ext2fs_extent *extent)
+{
+ struct extent_path *path;
+ struct ext3_extent_idx *ix;
+ struct ext3_extent_header *eh;
+ errcode_t retval;
+
+ EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
+
+ if (!(handle->fs->flags & EXT2_FLAG_RW))
+ return EXT2_ET_RO_FILSYS;
+
+ if (!handle->path)
+ return EXT2_ET_NO_CURRENT_NODE;
+
+ path = handle->path + handle->level;
+
+ if (path->entries >= path->max_entries)
+ return EXT2_ET_CANT_INSERT_EXTENT;
+
+ eh = (struct ext3_extent_header *) path->buf;
+ if (path->curr) {
+ ix = path->curr;
+ if (flags & EXT2_EXTENT_INSERT_AFTER) {
+ ix++;
+ path->left--;
+ }
+ } else
+ ix = EXT_FIRST_INDEX(eh);
+
+ path->curr = ix;
+
+ if (path->left > 0)
+ memmove(ix + 1, ix,
+ (path->left+1) * sizeof(struct ext3_extent_idx));
+ path->left++;
+ path->entries++;
+
+ eh = (struct ext3_extent_header *) path->buf;
+ eh->eh_entries = ext2fs_cpu_to_le16(path->entries);
+
+ retval = ext2fs_extent_replace(handle, 0, extent);
+ if (retval)
+ goto errout;
+
+ retval = update_path(handle);
+ if (retval)
+ goto errout;
+
+ return 0;
+
+errout:
+ ext2fs_extent_delete(handle, 0);
+ return retval;
+}
+
+errcode_t ext2fs_extent_delete(ext2_extent_handle_t handle,
+ int flags EXT2FS_ATTR((unused)))
+{
+ struct extent_path *path;
+ char *cp;
+ struct ext3_extent_header *eh;
+ errcode_t retval;
+
+ EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
+
+ if (!(handle->fs->flags & EXT2_FLAG_RW))
+ return EXT2_ET_RO_FILSYS;
+
+ if (!handle->path)
+ return EXT2_ET_NO_CURRENT_NODE;
+
+ path = handle->path + handle->level;
+ if (!path->curr)
+ return EXT2_ET_NO_CURRENT_NODE;
+
+ cp = path->curr;
+
+ if (path->left) {
+ memmove(cp, cp + sizeof(struct ext3_extent_idx),
+ path->left * sizeof(struct ext3_extent_idx));
+ path->left--;
+ } else {
+ struct ext3_extent_idx *ix = path->curr;
+ ix--;
+ path->curr = ix;
+ }
+ path->entries--;
+ if (path->entries == 0)
+ path->curr = 0;
+
+ eh = (struct ext3_extent_header *) path->buf;
+ eh->eh_entries = ext2fs_cpu_to_le16(path->entries);
+
+ retval = update_path(handle);
+
+ return retval;
+}
+
+errcode_t ext2fs_extent_get_info(ext2_extent_handle_t handle,
+ struct ext2_extent_info *info)
+{
+ struct extent_path *path;
+
+ EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
+
+ memset(info, 0, sizeof(struct ext2_extent_info));
+
+ path = handle->path + handle->level;
+ if (path) {
+ if (path->curr)
+ info->curr_entry = ((char *) path->curr - path->buf) /
+ sizeof(struct ext3_extent_idx);
+ else
+ info->curr_entry = 0;
+ info->num_entries = path->entries;
+ info->max_entries = path->max_entries;
+ info->bytes_avail = (path->max_entries - path->entries) *
+ sizeof(struct ext3_extent);
+ }
+
+ info->curr_level = handle->level;
+ info->max_depth = handle->max_depth;
+ info->max_lblk = ((__u64) 1 << 32) - 1;
+ info->max_pblk = ((__u64) 1 << 48) - 1;
+ info->max_len = (1UL << 15);
+ info->max_uninit_len = (1UL << 15) - 1;
+
+ return 0;
+}
+
+#ifdef DEBUG
+
+#include "debugfs.h"
+
+/*
+ * Hook in new commands into debugfs
+ */
+const char *debug_prog_name = "tst_extents";
+extern ss_request_table extent_cmds;
+ss_request_table *extra_cmds = &extent_cmds;
+
+ext2_ino_t current_ino = 0;
+ext2_extent_handle_t current_handle;
+
+void do_inode(int argc, char *argv[])
+{
+ ext2_ino_t inode;
+ int i;
+ struct ext3_extent_header *eh;
+ errcode_t retval;
+
+ if (check_fs_open(argv[0]))
+ return;
+
+ if (argc == 1) {
+ if (current_ino)
+ printf("Current inode is %d\n", current_ino);
+ else
+ printf("No current inode\n");
+ return;
+ }
+
+ if (common_inode_args_process(argc, argv, &inode, 0)) {
+ return;
+ }
+
+ current_ino = 0;
+
+ retval = ext2fs_extent_open(current_fs, inode, ¤t_handle);
+ if (retval) {
+ com_err(argv[1], retval, "while opening extent handle");
+ return;
+ }
+
+ current_ino = inode;
+
+ printf("Loaded inode %d\n", current_ino);
+
+ return;
+}
+
+void generic_goto_node(char *cmd_name, int op)
+{
+ struct ext2fs_extent extent;
+ errcode_t retval;
+
+ if (check_fs_open(cmd_name))
+ return;
+
+ if (!current_handle) {
+ com_err(cmd_name, 0, "Extent handle not open");
+ return;
+ }
+
+ retval = ext2fs_extent_get(current_handle, op, &extent);
+ if (retval) {
+ com_err(cmd_name, retval, 0);
+ return;
+ }
+ dbg_print_extent(0, &extent);
+}
+
+void do_current_node(int argc, char *argv[])
+{
+ generic_goto_node(argv[0], EXT2_EXTENT_CURRENT);
+}
+
+void do_root_node(int argc, char *argv[])
+{
+ generic_goto_node(argv[0], EXT2_EXTENT_ROOT);
+}
+
+void do_last_leaf(int argc, char *argv[])
+{
+ generic_goto_node(argv[0], EXT2_EXTENT_LAST_LEAF);
+}
+
+void do_first_sib(int argc, char *argv[])
+{
+ generic_goto_node(argv[0], EXT2_EXTENT_FIRST_SIB);
+}
+
+void do_last_sib(int argc, char *argv[])
+{
+ generic_goto_node(argv[0], EXT2_EXTENT_LAST_SIB);
+}
+
+void do_next_sib(int argc, char *argv[])
+{
+ generic_goto_node(argv[0], EXT2_EXTENT_NEXT_SIB);
+}
+
+void do_prev_sib(int argc, char *argv[])
+{
+ generic_goto_node(argv[0], EXT2_EXTENT_PREV_SIB);
+}
+
+void do_next_leaf(int argc, char *argv[])
+{
+ generic_goto_node(argv[0], EXT2_EXTENT_NEXT_LEAF);
+}
+
+void do_prev_leaf(int argc, char *argv[])
+{
+ generic_goto_node(argv[0], EXT2_EXTENT_PREV_LEAF);
+}
+
+void do_next(int argc, char *argv[])
+{
+ generic_goto_node(argv[0], EXT2_EXTENT_NEXT);
+}
+
+void do_prev(int argc, char *argv[])
+{
+ generic_goto_node(argv[0], EXT2_EXTENT_PREV);
+}
+
+void do_up(int argc, char *argv[])
+{
+ generic_goto_node(argv[0], EXT2_EXTENT_UP);
+}
+
+void do_down(int argc, char *argv[])
+{
+ generic_goto_node(argv[0], EXT2_EXTENT_DOWN);
+}
+
+void do_delete_node(int argc, char *argv[])
+{
+ errcode_t retval;
+ int err;
+
+ if (check_fs_read_write(argv[0]))
+ return;
+
+ retval = ext2fs_extent_delete(current_handle, 0);
+ if (retval) {
+ com_err(argv[0], retval, 0);
+ return;
+ }
+ do_current_node(argc, argv);
+}
+
+void do_replace_node(int argc, char *argv[])
+{
+ errcode_t retval;
+ struct ext2fs_extent extent;
+ int err;
+
+ if (check_fs_read_write(argv[0]))
+ return;
+
+ if (argc != 4) {
+ fprintf(stderr, "usage: %s <lblk> <len> <pblk>\n", argv[0]);
+ return;
+ }
+
+ extent.e_lblk = parse_ulong(argv[1], argv[0],
+ "logical block", &err);
+ if (err)
+ return;
+
+ extent.e_len = parse_ulong(argv[2], argv[0],
+ "logical block", &err);
+ if (err)
+ return;
+
+ extent.e_pblk = parse_ulong(argv[3], argv[0],
+ "logical block", &err);
+ if (err)
+ return;
+
+ retval = ext2fs_extent_replace(current_handle, 0, &extent);
+ if (retval) {
+ com_err(argv[0], retval, 0);
+ return;
+ }
+ do_current_node(argc, argv);
+}
+
+void do_insert_node(int argc, char *argv[])
+{
+ errcode_t retval;
+ struct ext2fs_extent extent;
+ char *cmd;
+ int err;
+ int flags = 0;
+
+ if (check_fs_read_write(argv[0]))
+ return;
+
+ cmd = argv[0];
+
+ if (argc > 2 && !strcmp(argv[1], "--after")) {
+ argc--;
+ argv++;
+ flags |= EXT2_EXTENT_INSERT_AFTER;
+ }
+
+ if (argc != 4) {
+ fprintf(stderr, "usage: %s <lblk> <len> <pblk>\n", cmd);
+ return;
+ }
+
+ extent.e_lblk = parse_ulong(argv[1], cmd,
+ "logical block", &err);
+ if (err)
+ return;
+
+ extent.e_len = parse_ulong(argv[2], cmd,
+ "length", &err);
+ if (err)
+ return;
+
+ extent.e_pblk = parse_ulong(argv[3], cmd,
+ "pysical block", &err);
+ if (err)
+ return;
+
+ retval = ext2fs_extent_insert(current_handle, flags, &extent);
+ if (retval) {
+ com_err(cmd, retval, 0);
+ return;
+ }
+ do_current_node(argc, argv);
+}
+
+void do_print_all(int argc, char **argv)
+{
+ struct ext2fs_extent extent;
+ errcode_t retval;
+ errcode_t end_err = EXT2_ET_EXTENT_NO_NEXT;
+ int op = EXT2_EXTENT_NEXT;
+ int first_op = EXT2_EXTENT_ROOT;
+
+
+ if (check_fs_open(argv[0]))
+ return;
+
+ if (!current_handle) {
+ com_err(argv[0], 0, "Extent handle not open");
+ return;
+ }
+
+ if (argc > 2) {
+ print_usage:
+ fprintf(stderr,
+ "Usage: %s [--leaf-only|--reverse|--reverse-leaf]\n",
+ argv[0]);
+ return;
+ }
+
+ if (argc == 2) {
+ if (!strcmp(argv[1], "--leaf-only"))
+ op = EXT2_EXTENT_NEXT_LEAF;
+ else if (!strcmp(argv[1], "--reverse")) {
+ op = EXT2_EXTENT_PREV;
+ first_op = EXT2_EXTENT_LAST_LEAF;
+ end_err = EXT2_ET_EXTENT_NO_PREV;
+ } else if (!strcmp(argv[1], "--reverse-leaf")) {
+ op = EXT2_EXTENT_PREV_LEAF;
+ first_op = EXT2_EXTENT_LAST_LEAF;
+ end_err = EXT2_ET_EXTENT_NO_PREV;
+ } else
+ goto print_usage;
+ }
+
+ retval = ext2fs_extent_get(current_handle, first_op, &extent);
+ if (retval) {
+ com_err(argv[0], retval, 0);
+ return;
+ }
+ dbg_print_extent(0, &extent);
+
+ while (1) {
+ retval = ext2fs_extent_get(current_handle, op, &extent);
+ if (retval == end_err)
+ break;
+
+ if (retval) {
+ com_err(argv[0], retval, 0);
+ return;
+ }
+ dbg_print_extent(0, &extent);
+ }
+}
+
+void do_info(int argc, char **argv)
+{
+ struct ext2_extent_info info;
+ errcode_t retval;
+
+ if (check_fs_open(argv[0]))
+ return;
+
+ if (!current_handle) {
+ com_err(argv[0], 0, "Extent handle not open");
+ return;
+ }
+
+ retval = ext2fs_extent_get_info(current_handle, &info);
+ if (retval) {
+ com_err(argv[0], retval, 0);
+ return;
+ }
+
+ printf("Current handle location: %d/%d (max: %d, bytes %d), level %d/%d\n",
+ info.curr_entry, info.num_entries, info.max_entries,
+ info.bytes_avail, info.curr_level, info.max_depth);
+ printf("\tmax lblk: %llu, max pblk: %llu\n", info.max_lblk,
+ info.max_pblk);
+ printf("\tmax_len: %u, max_uninit_len: %u\n", info.max_len,
+ info.max_uninit_len);
+}
+
+void do_goto_block(int argc, char **argv)
+{
+ struct ext2fs_extent extent;
+ errcode_t retval;
+ int op = EXT2_EXTENT_NEXT_LEAF;
+ blk_t blk;
+
+ if (check_fs_open(argv[0]))
+ return;
+
+ if (!current_handle) {
+ com_err(argv[0], 0, "Extent handle not open");
+ return;
+ }
+
+ if (argc != 2) {
+ fprintf(stderr, "%s block\n", argv[0]);
+ return;
+ }
+
+ if (strtoblk(argv[0], argv[1], &blk))
+ return;
+
+ retval = ext2fs_extent_goto(current_handle, (blk64_t) blk);
+ if (retval) {
+ com_err(argv[0], retval, "while trying to go to block %lu",
+ blk);
+ return;
+ }
+
+ generic_goto_node(argv[0], EXT2_EXTENT_CURRENT);
+}
+#endif
+
diff --git a/lib/ext2fs/extent_dbg.ct b/lib/ext2fs/extent_dbg.ct
new file mode 100644
index 0000000..41299fa
--- /dev/null
+++ b/lib/ext2fs/extent_dbg.ct
@@ -0,0 +1,68 @@
+#
+# Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
+# under the terms of the GNU Public License.
+#
+command_table extent_cmds;
+
+request do_inode, "Open an inode",
+ inode;
+
+request do_current_node, "Current extent node",
+ current_node, current;
+
+request do_root_node, "Goto root extent",
+ root_node, root;
+
+request do_last_leaf, "Goto last leaf",
+ last_leaf;
+
+request do_first_sib, "Goto first sibling",
+ first_sibling, first_sib;
+
+request do_last_sib, "Goto last sibling",
+ last_sibling, last_sib;
+
+request do_next_sib, "Goto next sibling",
+ next_sibling, next_sib, ns;
+
+request do_prev_sib, "Goto previous sibling",
+ prev_sibling, prev_sib, ps;
+
+request do_next_leaf, "Goto next leaf",
+ next_leaf, nl;
+
+request do_prev_leaf, "Goto previous leaf",
+ prev_leaf, pl;
+
+request do_next, "Goto next node",
+ next, n;
+
+request do_prev, "Goto previous node",
+ previous, prev, p;
+
+request do_up, "Up node",
+ up_node, up, u;
+
+request do_down, "Down node",
+ down_node, down, d;
+
+request do_delete_node, "Delete node",
+ delete_node, delete;
+
+request do_insert_node, "Insert node",
+ insert_node, insert;
+
+request do_replace_node, "Insert node",
+ replace_node, replace;
+
+request do_print_all, "Iterate over all nodes and print them",
+ print_all, all;
+
+request do_goto_block, "Goto extent containing specified block",
+ goto_block, goto;
+
+request do_info, "Print extent info",
+ info;
+
+end;
+
diff --git a/lib/ext2fs/freefs.c b/lib/ext2fs/freefs.c
index 029ffaa..d6ac901 100644
--- a/lib/ext2fs/freefs.c
+++ b/lib/ext2fs/freefs.c
@@ -58,41 +58,6 @@
ext2fs_free_mem(&fs);
}
-void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap)
-{
- if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_GENERIC_BITMAP))
- return;
-
- bitmap->magic = 0;
- if (bitmap->description) {
- ext2fs_free_mem(&bitmap->description);
- bitmap->description = 0;
- }
- if (bitmap->bitmap) {
- ext2fs_free_mem(&bitmap->bitmap);
- bitmap->bitmap = 0;
- }
- ext2fs_free_mem(&bitmap);
-}
-
-void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap)
-{
- if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP))
- return;
-
- bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
- ext2fs_free_generic_bitmap(bitmap);
-}
-
-void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap)
-{
- if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP))
- return;
-
- bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
- ext2fs_free_generic_bitmap(bitmap);
-}
-
/*
* Free the inode cache structure
*/
diff --git a/lib/ext2fs/gen_bitmap.c b/lib/ext2fs/gen_bitmap.c
index 700affa..66172e5 100644
--- a/lib/ext2fs/gen_bitmap.c
+++ b/lib/ext2fs/gen_bitmap.c
@@ -1,5 +1,5 @@
/*
- * gen_bitmap.c --- Generic bitmap routines that used to be inlined.
+ * gen_bitmap.c --- Generic (32-bit) bitmap routines
*
* Copyright (C) 2001 Theodore Ts'o.
*
@@ -27,6 +27,144 @@
#include "ext2_fs.h"
#include "ext2fs.h"
+struct ext2fs_struct_generic_bitmap {
+ errcode_t magic;
+ ext2_filsys fs;
+ __u32 start, end;
+ __u32 real_end;
+ char * description;
+ char * bitmap;
+ errcode_t base_error_code;
+ __u32 reserved[7];
+};
+
+/*
+ * Used by previously inlined function, so we have to export this and
+ * not change the function signature
+ */
+void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
+ int code, unsigned long arg)
+{
+#ifndef OMIT_COM_ERR
+ if (bitmap->description)
+ com_err(0, bitmap->base_error_code+code,
+ "#%lu for %s", arg, bitmap->description);
+ else
+ com_err(0, bitmap->base_error_code + code, "#%lu", arg);
+#endif
+}
+
+static errcode_t check_magic(ext2fs_generic_bitmap bitmap)
+{
+ if (!bitmap || !((bitmap->magic == EXT2_ET_MAGIC_GENERIC_BITMAP) ||
+ (bitmap->magic == EXT2_ET_MAGIC_INODE_BITMAP) ||
+ (bitmap->magic == EXT2_ET_MAGIC_BLOCK_BITMAP)))
+ return EXT2_ET_MAGIC_GENERIC_BITMAP;
+ return 0;
+}
+
+errcode_t ext2fs_make_generic_bitmap(errcode_t magic, ext2_filsys fs,
+ __u32 start, __u32 end, __u32 real_end,
+ const char *descr, char *init_map,
+ ext2fs_generic_bitmap *ret)
+{
+ ext2fs_generic_bitmap bitmap;
+ errcode_t retval;
+ size_t size;
+
+ retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap),
+ &bitmap);
+ if (retval)
+ return retval;
+
+ bitmap->magic = magic;
+ bitmap->fs = fs;
+ bitmap->start = start;
+ bitmap->end = end;
+ bitmap->real_end = real_end;
+ switch (magic) {
+ case EXT2_ET_MAGIC_INODE_BITMAP:
+ bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK;
+ break;
+ case EXT2_ET_MAGIC_BLOCK_BITMAP:
+ bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
+ break;
+ default:
+ bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
+ }
+ if (descr) {
+ retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description);
+ if (retval) {
+ ext2fs_free_mem(&bitmap);
+ return retval;
+ }
+ strcpy(bitmap->description, descr);
+ } else
+ bitmap->description = 0;
+
+ size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
+ retval = ext2fs_get_mem(size, &bitmap->bitmap);
+ if (retval) {
+ ext2fs_free_mem(&bitmap->description);
+ ext2fs_free_mem(&bitmap);
+ return retval;
+ }
+
+ if (init_map)
+ memcpy(bitmap->bitmap, init_map, size);
+ else
+ memset(bitmap->bitmap, 0, size);
+ *ret = bitmap;
+ return 0;
+}
+
+errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
+ __u32 end,
+ __u32 real_end,
+ const char *descr,
+ ext2fs_generic_bitmap *ret)
+{
+ return ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_GENERIC_BITMAP, 0,
+ start, end, real_end, descr, 0, ret);
+}
+
+errcode_t ext2fs_copy_generic_bitmap(ext2fs_generic_bitmap src,
+ ext2fs_generic_bitmap *dest)
+{
+ return (ext2fs_make_generic_bitmap(src->magic, src->fs,
+ src->start, src->end,
+ src->real_end,
+ src->description, src->bitmap,
+ dest));
+}
+
+void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap)
+{
+ if (check_magic(bitmap))
+ return;
+
+ bitmap->magic = 0;
+ if (bitmap->description) {
+ ext2fs_free_mem(&bitmap->description);
+ bitmap->description = 0;
+ }
+ if (bitmap->bitmap) {
+ ext2fs_free_mem(&bitmap->bitmap);
+ bitmap->bitmap = 0;
+ }
+ ext2fs_free_mem(&bitmap);
+}
+
+int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
+ blk_t bitno)
+{
+ if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
+ ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno);
+ return 0;
+ }
+ return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap);
+}
+
int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
__u32 bitno)
{
@@ -46,3 +184,191 @@
}
return ext2fs_clear_bit(bitno - bitmap->start, bitmap->bitmap);
}
+
+__u32 ext2fs_get_generic_bitmap_start(ext2fs_generic_bitmap bitmap)
+{
+ return bitmap->start;
+}
+
+__u32 ext2fs_get_generic_bitmap_end(ext2fs_generic_bitmap bitmap)
+{
+ return bitmap->end;
+}
+
+void ext2fs_clear_generic_bitmap(ext2fs_generic_bitmap bitmap)
+{
+ if (check_magic(bitmap))
+ return;
+
+ memset(bitmap->bitmap, 0,
+ (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
+}
+
+errcode_t ext2fs_fudge_generic_bitmap_end(ext2fs_inode_bitmap bitmap,
+ errcode_t magic, errcode_t neq,
+ ext2_ino_t end, ext2_ino_t *oend)
+{
+ EXT2_CHECK_MAGIC(bitmap, magic);
+
+ if (end > bitmap->real_end)
+ return neq;
+ if (oend)
+ *oend = bitmap->end;
+ bitmap->end = end;
+ return 0;
+}
+
+errcode_t ext2fs_resize_generic_bitmap(errcode_t magic,
+ __u32 new_end, __u32 new_real_end,
+ ext2fs_generic_bitmap bmap)
+{
+ errcode_t retval;
+ size_t size, new_size;
+ __u32 bitno;
+
+ if (!bmap || (bmap->magic != magic))
+ return magic;
+
+ /*
+ * If we're expanding the bitmap, make sure all of the new
+ * parts of the bitmap are zero.
+ */
+ if (new_end > bmap->end) {
+ bitno = bmap->real_end;
+ if (bitno > new_end)
+ bitno = new_end;
+ for (; bitno > bmap->end; bitno--)
+ ext2fs_clear_bit(bitno - bmap->start, bmap->bitmap);
+ }
+ if (new_real_end == bmap->real_end) {
+ bmap->end = new_end;
+ return 0;
+ }
+
+ size = ((bmap->real_end - bmap->start) / 8) + 1;
+ new_size = ((new_real_end - bmap->start) / 8) + 1;
+
+ if (size != new_size) {
+ retval = ext2fs_resize_mem(size, new_size, &bmap->bitmap);
+ if (retval)
+ return retval;
+ }
+ if (new_size > size)
+ memset(bmap->bitmap + size, 0, new_size - size);
+
+ bmap->end = new_end;
+ bmap->real_end = new_real_end;
+ return 0;
+}
+
+errcode_t ext2fs_compare_generic_bitmap(errcode_t magic, errcode_t neq,
+ ext2fs_generic_bitmap bm1,
+ ext2fs_generic_bitmap bm2)
+{
+ blk_t i;
+
+ if (!bm1 || bm1->magic != magic)
+ return magic;
+ if (!bm2 || bm2->magic != magic)
+ return magic;
+
+ if ((bm1->start != bm2->start) ||
+ (bm1->end != bm2->end) ||
+ (memcmp(bm1->bitmap, bm2->bitmap,
+ (size_t) (bm1->end - bm1->start)/8)))
+ return neq;
+
+ for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
+ if (ext2fs_fast_test_block_bitmap(bm1, i) !=
+ ext2fs_fast_test_block_bitmap(bm2, i))
+ return neq;
+
+ return 0;
+}
+
+void ext2fs_set_generic_bitmap_padding(ext2fs_generic_bitmap map)
+{
+ __u32 i, j;
+
+ /* Protect loop from wrap-around if map->real_end is maxed */
+ for (i=map->end+1, j = i - map->start;
+ i <= map->real_end && i > map->end;
+ i++, j++)
+ ext2fs_set_bit(j, map->bitmap);
+}
+
+errcode_t ext2fs_get_generic_bitmap_range(ext2fs_generic_bitmap bmap,
+ errcode_t magic,
+ __u32 start, __u32 num,
+ void *out)
+{
+ if (!bmap || (bmap->magic != magic))
+ return magic;
+
+ if ((start < bmap->start) || (start+num-1 > bmap->real_end))
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ memcpy(out, bmap->bitmap + (start >> 3), (num+7) >> 3);
+ return 0;
+}
+
+errcode_t ext2fs_set_generic_bitmap_range(ext2fs_generic_bitmap bmap,
+ errcode_t magic,
+ __u32 start, __u32 num,
+ void *in)
+{
+ if (!bmap || (bmap->magic != magic))
+ return magic;
+
+ if ((start < bmap->start) || (start+num-1 > bmap->real_end))
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ memcpy(bmap->bitmap + (start >> 3), in, (num+7) >> 3);
+ return 0;
+}
+
+int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
+ blk_t block, int num)
+{
+ int i;
+
+ if ((block < bitmap->start) || (block+num-1 > bitmap->real_end)) {
+ ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
+ block, bitmap->description);
+ return 0;
+ }
+ for (i=0; i < num; i++) {
+ if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
+ return 0;
+ }
+ return 1;
+}
+
+void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+ blk_t block, int num)
+{
+ int i;
+
+ if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+ ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
+ bitmap->description);
+ return;
+ }
+ for (i=0; i < num; i++)
+ ext2fs_fast_set_bit(block + i - bitmap->start, bitmap->bitmap);
+}
+
+void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+ blk_t block, int num)
+{
+ int i;
+
+ if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+ ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
+ bitmap->description);
+ return;
+ }
+ for (i=0; i < num; i++)
+ ext2fs_fast_clear_bit(block + i - bitmap->start,
+ bitmap->bitmap);
+}
diff --git a/lib/ext2fs/icount.c b/lib/ext2fs/icount.c
index 2905676..bec0f5f 100644
--- a/lib/ext2fs/icount.c
+++ b/lib/ext2fs/icount.c
@@ -43,7 +43,7 @@
struct ext2_icount_el {
ext2_ino_t ino;
- __u16 count;
+ __u32 count;
};
struct ext2_icount {
@@ -60,6 +60,15 @@
TDB_CONTEXT *tdb;
};
+/*
+ * We now use a 32-bit counter field because it doesn't cost us
+ * anything extra for the in-memory data structure, due to alignment
+ * padding. But there's no point changing the interface if most of
+ * the time we only care if the number is bigger than 65,000 or not.
+ * So use the following translation function to return a 16-bit count.
+ */
+#define icount_16_xlate(x) (((x) > 65500) ? 65500 : (x))
+
void ext2fs_free_icount(ext2_icount_t icount)
{
if (!icount)
@@ -398,7 +407,7 @@
}
static errcode_t set_inode_count(ext2_icount_t icount, ext2_ino_t ino,
- __u16 count)
+ __u32 count)
{
struct ext2_icount_el *el;
TDB_DATA key, data;
@@ -407,7 +416,7 @@
key.dptr = (unsigned char *) &ino;
key.dsize = sizeof(ext2_ino_t);
data.dptr = (unsigned char *) &count;
- data.dsize = sizeof(__u16);
+ data.dsize = sizeof(__u32);
if (count) {
if (tdb_store(icount->tdb, key, data, TDB_REPLACE))
return tdb_error(icount->tdb) +
@@ -429,7 +438,7 @@
}
static errcode_t get_inode_count(ext2_icount_t icount, ext2_ino_t ino,
- __u16 *count)
+ __u32 *count)
{
struct ext2_icount_el *el;
TDB_DATA key, data;
@@ -444,7 +453,7 @@
return tdb_error(icount->tdb) + EXT2_ET_TDB_SUCCESS;
}
- *count = *((__u16 *) data.dptr);
+ *count = *((__u32 *) data.dptr);
free(data.dptr);
return 0;
}
@@ -483,6 +492,7 @@
errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, __u16 *ret)
{
+ __u32 val;
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
if (!ino || (ino > icount->num_inodes))
@@ -497,14 +507,15 @@
*ret = 0;
return 0;
}
- get_inode_count(icount, ino, ret);
+ get_inode_count(icount, ino, &val);
+ *ret = icount_16_xlate(val);
return 0;
}
errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
__u16 *ret)
{
- __u16 curr_value;
+ __u32 curr_value;
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
@@ -554,14 +565,14 @@
if (icount->multiple)
ext2fs_mark_inode_bitmap(icount->multiple, ino);
if (ret)
- *ret = curr_value;
+ *ret = icount_16_xlate(curr_value);
return 0;
}
errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
__u16 *ret)
{
- __u16 curr_value;
+ __u32 curr_value;
if (!ino || (ino > icount->num_inodes))
return EXT2_ET_INVALID_ARGUMENT;
@@ -597,7 +608,7 @@
ext2fs_unmark_inode_bitmap(icount->multiple, ino);
if (ret)
- *ret = curr_value;
+ *ret = icount_16_xlate(curr_value);
return 0;
}
diff --git a/lib/ext2fs/imager.c b/lib/ext2fs/imager.c
index ac8309c..9f7534a 100644
--- a/lib/ext2fs/imager.c
+++ b/lib/ext2fs/imager.c
@@ -277,11 +277,12 @@
*/
errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
{
- char *ptr;
- int c, size;
- char zero_buf[1024];
- ssize_t actual;
- errcode_t retval;
+ ext2fs_generic_bitmap bmap;
+ errcode_t err, retval;
+ ssize_t actual;
+ __u32 itr, cnt, size;
+ int c, total_size;
+ char buf[1024];
if (flags & IMAGER_FLAG_INODEMAP) {
if (!fs->inode_map) {
@@ -289,7 +290,10 @@
if (retval)
return retval;
}
- ptr = fs->inode_map->bitmap;
+ bmap = fs->inode_map;
+ err = EXT2_ET_MAGIC_INODE_BITMAP;
+ itr = 1;
+ cnt = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
} else {
if (!fs->block_map) {
@@ -297,43 +301,51 @@
if (retval)
return retval;
}
- ptr = fs->block_map->bitmap;
+ bmap = fs->block_map;
+ err = EXT2_ET_MAGIC_BLOCK_BITMAP;
+ itr = fs->super->s_first_data_block;
+ cnt = EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count;
size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
}
- size = size * fs->group_desc_count;
+ total_size = size * fs->group_desc_count;
- actual = write(fd, ptr, size);
- if (actual == -1) {
- retval = errno;
- goto errout;
+ while (cnt > 0) {
+ size = sizeof(buf);
+ if (size > (cnt >> 3))
+ size = (cnt >> 3);
+
+ retval = ext2fs_get_generic_bitmap_range(bmap,
+ err, itr, size << 3, buf);
+ if (retval)
+ return retval;
+
+ actual = write(fd, buf, size);
+ if (actual == -1)
+ return errno;
+ if (actual != (int) size)
+ return EXT2_ET_SHORT_READ;
+
+ itr += size << 3;
+ cnt -= size << 3;
}
- if (actual != size) {
- retval = EXT2_ET_SHORT_WRITE;
- goto errout;
- }
- size = size % fs->blocksize;
- memset(zero_buf, 0, sizeof(zero_buf));
+
+ size = total_size % fs->blocksize;
+ memset(buf, 0, sizeof(buf));
if (size) {
size = fs->blocksize - size;
while (size) {
c = size;
- if (c > (int) sizeof(zero_buf))
- c = sizeof(zero_buf);
- actual = write(fd, zero_buf, c);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != c) {
- retval = EXT2_ET_SHORT_WRITE;
- goto errout;
- }
+ if (c > (int) sizeof(buf))
+ c = sizeof(buf);
+ actual = write(fd, buf, c);
+ if (actual == -1)
+ return errno;
+ if (actual != c)
+ return EXT2_ET_SHORT_WRITE;
size -= c;
}
}
- retval = 0;
-errout:
- return (retval);
+ return 0;
}
@@ -342,10 +354,12 @@
*/
errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
{
- char *ptr, *buf = 0;
- int size;
- ssize_t actual;
- errcode_t retval;
+ ext2fs_generic_bitmap bmap;
+ errcode_t err, retval;
+ __u32 itr, cnt;
+ char buf[1024];
+ unsigned int size;
+ ssize_t actual;
if (flags & IMAGER_FLAG_INODEMAP) {
if (!fs->inode_map) {
@@ -353,7 +367,10 @@
if (retval)
return retval;
}
- ptr = fs->inode_map->bitmap;
+ bmap = fs->inode_map;
+ err = EXT2_ET_MAGIC_INODE_BITMAP;
+ itr = 1;
+ cnt = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
} else {
if (!fs->block_map) {
@@ -361,29 +378,31 @@
if (retval)
return retval;
}
- ptr = fs->block_map->bitmap;
+ bmap = fs->block_map;
+ err = EXT2_ET_MAGIC_BLOCK_BITMAP;
+ itr = fs->super->s_first_data_block;
+ cnt = EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count;
size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
}
- size = size * fs->group_desc_count;
- buf = malloc(size);
- if (!buf)
- return ENOMEM;
+ while (cnt > 0) {
+ size = sizeof(buf);
+ if (size > (cnt >> 3))
+ size = (cnt >> 3);
- actual = read(fd, buf, size);
- if (actual == -1) {
- retval = errno;
- goto errout;
+ actual = read(fd, buf, size);
+ if (actual == -1)
+ return errno;
+ if (actual != (int) size)
+ return EXT2_ET_SHORT_READ;
+
+ retval = ext2fs_set_generic_bitmap_range(bmap,
+ err, itr, size << 3, buf);
+ if (retval)
+ return retval;
+
+ itr += size << 3;
+ cnt -= size << 3;
}
- if (actual != size) {
- retval = EXT2_ET_SHORT_WRITE;
- goto errout;
- }
- memcpy(ptr, buf, size);
-
- retval = 0;
-errout:
- if (buf)
- free(buf);
- return (retval);
+ return 0;
}
diff --git a/lib/ext2fs/ind_block.c b/lib/ext2fs/ind_block.c
index 3519048..efd7fb1 100644
--- a/lib/ext2fs/ind_block.c
+++ b/lib/ext2fs/ind_block.c
@@ -22,9 +22,11 @@
errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf)
{
errcode_t retval;
+#ifdef WORDS_BIGENDIAN
blk_t *block_nr;
int i;
int limit = fs->blocksize >> 2;
+#endif
if ((fs->flags & EXT2_FLAG_IMAGE_FILE) &&
(fs->io != fs->image_io))
@@ -34,31 +36,29 @@
if (retval)
return retval;
}
-#ifdef EXT2FS_ENABLE_SWAPFS
- if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_READ)) {
- block_nr = (blk_t *) buf;
- for (i = 0; i < limit; i++, block_nr++)
- *block_nr = ext2fs_swab32(*block_nr);
- }
+#ifdef WORDS_BIGENDIAN
+ block_nr = (blk_t *) buf;
+ for (i = 0; i < limit; i++, block_nr++)
+ *block_nr = ext2fs_swab32(*block_nr);
#endif
return 0;
}
errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf)
{
+#ifdef WORDS_BIGENDIAN
blk_t *block_nr;
int i;
int limit = fs->blocksize >> 2;
+#endif
if (fs->flags & EXT2_FLAG_IMAGE_FILE)
return 0;
-#ifdef EXT2FS_ENABLE_SWAPFS
- if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_WRITE)) {
- block_nr = (blk_t *) buf;
- for (i = 0; i < limit; i++, block_nr++)
- *block_nr = ext2fs_swab32(*block_nr);
- }
+#ifdef WORDS_BIGENDIAN
+ block_nr = (blk_t *) buf;
+ for (i = 0; i < limit; i++, block_nr++)
+ *block_nr = ext2fs_swab32(*block_nr);
#endif
return io_channel_write_blk(fs->io, blk, 1, buf);
}
diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c
index 7d06860..c2e00e8 100644
--- a/lib/ext2fs/initialize.c
+++ b/lib/ext2fs/initialize.c
@@ -67,7 +67,7 @@
{
struct ext2_super_block *sb = fs->super;
unsigned long bpg = sb->s_blocks_per_group;
- unsigned int gdpb = fs->blocksize / sizeof(struct ext2_group_desc);
+ unsigned int gdpb = EXT2_DESC_PER_BLOCK(sb);
unsigned long max_blocks = 0xffffffff;
unsigned long rsv_groups;
unsigned int rsv_gdb;
@@ -377,6 +377,7 @@
fs->group_desc[i].bg_free_inodes_count =
fs->super->s_inodes_per_group;
fs->group_desc[i].bg_used_dirs_count = 0;
+ ext2fs_group_desc_csum_set(fs, i);
}
c = (char) 255;
diff --git a/lib/ext2fs/inode.c b/lib/ext2fs/inode.c
index 7a0cf4e..bd568b3 100644
--- a/lib/ext2fs/inode.c
+++ b/lib/ext2fs/inode.c
@@ -167,6 +167,9 @@
if (EXT2_HAS_COMPAT_FEATURE(fs->super,
EXT2_FEATURE_COMPAT_LAZY_BG))
scan->scan_flags |= EXT2_SF_DO_LAZY;
+ if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
+ scan->scan_flags |= EXT2_SF_DO_LAZY;
*ret_scan = scan;
return 0;
}
@@ -218,18 +221,29 @@
*/
static errcode_t get_next_blockgroup(ext2_inode_scan scan)
{
+ ext2_filsys fs = scan->fs;
+
scan->current_group++;
scan->groups_left--;
-
- scan->current_block = scan->fs->
- group_desc[scan->current_group].bg_inode_table;
+
+ scan->current_block =fs->group_desc[scan->current_group].bg_inode_table;
scan->current_inode = scan->current_group *
- EXT2_INODES_PER_GROUP(scan->fs->super);
+ EXT2_INODES_PER_GROUP(fs->super);
scan->bytes_left = 0;
- scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
- scan->blocks_left = scan->fs->inode_blocks_per_group;
+ scan->inodes_left = EXT2_INODES_PER_GROUP(fs->super);
+ scan->blocks_left = fs->inode_blocks_per_group;
+ if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+ scan->inodes_left -=
+ fs->group_desc[scan->current_group].bg_itable_unused;
+ scan->blocks_left =
+ (scan->inodes_left +
+ (fs->blocksize / scan->inode_size - 1)) *
+ scan->inode_size / fs->blocksize;
+ }
+
return 0;
}
@@ -417,6 +431,8 @@
(scan->fs->group_desc[scan->current_group].bg_flags &
EXT2_BG_INODE_UNINIT))
goto force_new_group;
+ if (scan->inodes_left == 0)
+ goto force_new_group;
if (scan->current_block == 0) {
if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) {
goto force_new_group;
@@ -453,32 +469,28 @@
scan->ptr += scan->inode_size - extra_bytes;
scan->bytes_left -= scan->inode_size - extra_bytes;
-#ifdef EXT2FS_ENABLE_SWAPFS
+#ifdef WORDS_BIGENDIAN
memset(inode, 0, bufsize);
- if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
- ext2fs_swap_inode_full(scan->fs,
- (struct ext2_inode_large *) inode,
- (struct ext2_inode_large *) scan->temp_buffer,
- 0, bufsize);
- else
+ ext2fs_swap_inode_full(scan->fs,
+ (struct ext2_inode_large *) inode,
+ (struct ext2_inode_large *) scan->temp_buffer,
+ 0, bufsize);
+#else
+ *inode = *((struct ext2_inode *) scan->temp_buffer);
#endif
- *inode = *((struct ext2_inode *) scan->temp_buffer);
if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES)
retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES;
} else {
-#ifdef EXT2FS_ENABLE_SWAPFS
+#ifdef WORDS_BIGENDIAN
memset(inode, 0, bufsize);
- if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
- ext2fs_swap_inode_full(scan->fs,
+ ext2fs_swap_inode_full(scan->fs,
(struct ext2_inode_large *) inode,
(struct ext2_inode_large *) scan->ptr,
0, bufsize);
- else
+#else
+ memcpy(inode, scan->ptr, bufsize);
#endif
- memcpy(inode, scan->ptr, bufsize);
scan->ptr += scan->inode_size;
scan->bytes_left -= scan->inode_size;
if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK)
@@ -583,12 +595,10 @@
block_nr++;
}
-#ifdef EXT2FS_ENABLE_SWAPFS
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
- ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) inode,
- (struct ext2_inode_large *) inode,
- 0, bufsize);
+#ifdef WORDS_BIGENDIAN
+ ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) inode,
+ (struct ext2_inode_large *) inode,
+ 0, bufsize);
#endif
/* Update the inode cache */
@@ -657,16 +667,14 @@
w_inode = &temp_inode;
memset(w_inode, 0, length);
-#ifdef EXT2FS_ENABLE_SWAPFS
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
- ext2fs_swap_inode_full(fs, w_inode,
- (struct ext2_inode_large *) inode,
- 1, bufsize);
- else
+#ifdef WORDS_BIGENDIAN
+ ext2fs_swap_inode_full(fs, w_inode,
+ (struct ext2_inode_large *) inode,
+ 1, bufsize);
+#else
+ memcpy(w_inode, inode, bufsize);
#endif
- memcpy(w_inode, inode, bufsize);
-
+
group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
EXT2_INODE_SIZE(fs->super);
diff --git a/lib/ext2fs/inode_io.c b/lib/ext2fs/inode_io.c
index b5c08b9..0e23494 100644
--- a/lib/ext2fs/inode_io.c
+++ b/lib/ext2fs/inode_io.c
@@ -56,7 +56,11 @@
static errcode_t inode_flush(io_channel channel);
static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
int size, const void *data);
-
+static errcode_t inode_read_blk64(io_channel channel,
+ unsigned long long block, int count, void *data);
+static errcode_t inode_write_blk64(io_channel channel,
+ unsigned long long block, int count, const void *data);
+
static struct struct_io_manager struct_inode_manager = {
EXT2_ET_MAGIC_IO_MANAGER,
"Inode I/O Manager",
@@ -66,7 +70,11 @@
inode_read_blk,
inode_write_blk,
inode_flush,
- inode_write_byte
+ inode_write_byte,
+ NULL,
+ NULL,
+ inode_read_blk64,
+ inode_write_blk64
};
io_manager inode_io_manager = &struct_inode_manager;
@@ -197,8 +205,8 @@
}
-static errcode_t inode_read_blk(io_channel channel, unsigned long block,
- int count, void *buf)
+static errcode_t inode_read_blk64(io_channel channel,
+ unsigned long long block, int count, void *buf)
{
struct inode_private_data *data;
errcode_t retval;
@@ -217,8 +225,14 @@
return ext2fs_file_read(data->file, buf, count, 0);
}
-static errcode_t inode_write_blk(io_channel channel, unsigned long block,
- int count, const void *buf)
+static errcode_t inode_read_blk(io_channel channel, unsigned long block,
+ int count, void *buf)
+{
+ return inode_read_blk64(channel, block, count, buf);
+}
+
+static errcode_t inode_write_blk64(io_channel channel,
+ unsigned long long block, int count, const void *buf)
{
struct inode_private_data *data;
errcode_t retval;
@@ -237,6 +251,12 @@
return ext2fs_file_write(data->file, buf, count, 0);
}
+static errcode_t inode_write_blk(io_channel channel, unsigned long block,
+ int count, const void *buf)
+{
+ return inode_write_blk64(channel, block, count, buf);
+}
+
static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
int size, const void *buf)
{
diff --git a/lib/ext2fs/ismounted.c b/lib/ext2fs/ismounted.c
index 684e91e..d6573ad 100644
--- a/lib/ext2fs/ismounted.c
+++ b/lib/ext2fs/ismounted.c
@@ -251,10 +251,8 @@
if (!(f = fopen("/proc/swaps", "r")))
return 0;
/* Skip the first line */
- fgets(buf, sizeof(buf), f);
- while (!feof(f)) {
- if (!fgets(buf, sizeof(buf), f))
- break;
+ if (fgets(buf, sizeof(buf), f))
+ while (fgets(buf, sizeof(buf), f)) {
if ((cp = strchr(buf, ' ')) != NULL)
*cp = 0;
if ((cp = strchr(buf, '\t')) != NULL)
diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c
index d705b1c..fc54afe 100644
--- a/lib/ext2fs/openfs.c
+++ b/lib/ext2fs/openfs.c
@@ -39,11 +39,10 @@
(i < fs->super->s_first_meta_bg))
return (group_block + i + 1);
- bg = (fs->blocksize / sizeof (struct ext2_group_desc)) * i;
+ bg = EXT2_DESC_PER_BLOCK(fs->super) * i;
if (ext2fs_bg_has_super(fs, bg))
has_super = 1;
- ret_blk = (fs->super->s_first_data_block + has_super +
- (bg * fs->super->s_blocks_per_group));
+ ret_blk = ext2fs_group_first_block(fs, bg) + has_super;
/*
* If group_block is not the normal value, we're trying to use
* the backup group descriptors and superblock --- so use the
@@ -87,10 +86,13 @@
errcode_t retval;
unsigned long i;
__u32 features;
- int j, groups_per_block, blocks_per_group, io_flags;
+ int groups_per_block, blocks_per_group, io_flags;
blk_t group_block, blk;
char *dest, *cp;
+#ifdef WORDS_BIGENDIAN
struct ext2_group_desc *gdp;
+ int j;
+#endif
EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER);
@@ -178,12 +180,13 @@
if (fs->orig_super)
memcpy(fs->orig_super, fs->super, SUPERBLOCK_SIZE);
-#ifdef EXT2FS_ENABLE_SWAPFS
- if ((fs->super->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC)) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES)) {
- fs->flags |= EXT2_FLAG_SWAP_BYTES;
-
- ext2fs_swap_super(fs->super);
+#ifdef WORDS_BIGENDIAN
+ fs->flags |= EXT2_FLAG_SWAP_BYTES;
+ ext2fs_swap_super(fs->super);
+#else
+ if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
+ retval = EXT2_ET_UNIMPLEMENTED;
+ goto cleanup;
}
#endif
@@ -287,24 +290,38 @@
if (!group_block)
group_block = fs->super->s_first_data_block;
dest = (char *) fs->group_desc;
- groups_per_block = fs->blocksize / sizeof(struct ext2_group_desc);
+ groups_per_block = EXT2_DESC_PER_BLOCK(fs->super);
for (i=0 ; i < fs->desc_blocks; i++) {
blk = ext2fs_descriptor_block_loc(fs, group_block, i);
retval = io_channel_read_blk(fs->io, blk, 1, dest);
if (retval)
goto cleanup;
-#ifdef EXT2FS_ENABLE_SWAPFS
- if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- gdp = (struct ext2_group_desc *) dest;
- for (j=0; j < groups_per_block; j++)
- ext2fs_swap_group_desc(gdp++);
- }
+#ifdef WORDS_BIGENDIAN
+ gdp = (struct ext2_group_desc *) dest;
+ for (j=0; j < groups_per_block; j++)
+ ext2fs_swap_group_desc(gdp++);
#endif
dest += fs->blocksize;
}
fs->stride = fs->super->s_raid_stride;
+ /*
+ * If recovery is from backup superblock, Clear _UNININT flags &
+ * reset bg_itable_unused to zero
+ */
+ if (superblock > 1 && EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+ struct ext2_group_desc *gd;
+ for (i = 0, gd = fs->group_desc; i < fs->group_desc_count;
+ i++, gd++) {
+ gd->bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
+ gd->bg_flags &= ~EXT2_BG_INODE_UNINIT;
+ gd->bg_itable_unused = 0;
+ }
+ ext2fs_mark_super_dirty(fs);
+ }
+
fs->flags &= ~EXT2_FLAG_NOFREE_ON_ERROR;
*ret_fs = fs;
return 0;
diff --git a/lib/ext2fs/read_bb.c b/lib/ext2fs/read_bb.c
index c717adc..ff7e292 100644
--- a/lib/ext2fs/read_bb.c
+++ b/lib/ext2fs/read_bb.c
@@ -86,8 +86,8 @@
rb.bb_list = *bb_list;
rb.err = 0;
- retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, 0, 0,
- mark_bad_block, &rb);
+ retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, BLOCK_FLAG_READ_ONLY,
+ 0, mark_bad_block, &rb);
if (retval)
return retval;
diff --git a/lib/ext2fs/rs_bitmap.c b/lib/ext2fs/rs_bitmap.c
deleted file mode 100644
index 46653f0..0000000
--- a/lib/ext2fs/rs_bitmap.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * rs_bitmap.c --- routine for changing the size of a bitmap
- *
- * Copyright (C) 1996, 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 <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <time.h>
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ext2_fs.h"
-#include "ext2fs.h"
-
-errcode_t ext2fs_resize_generic_bitmap(__u32 new_end, __u32 new_real_end,
- ext2fs_generic_bitmap bmap)
-{
- errcode_t retval;
- size_t size, new_size;
- __u32 bitno;
-
- if (!bmap)
- return EXT2_ET_INVALID_ARGUMENT;
-
- EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_GENERIC_BITMAP);
-
- /*
- * If we're expanding the bitmap, make sure all of the new
- * parts of the bitmap are zero.
- */
- if (new_end > bmap->end) {
- bitno = bmap->real_end;
- if (bitno > new_end)
- bitno = new_end;
- for (; bitno > bmap->end; bitno--)
- ext2fs_clear_bit(bitno - bmap->start, bmap->bitmap);
- }
- if (new_real_end == bmap->real_end) {
- bmap->end = new_end;
- return 0;
- }
-
- size = ((bmap->real_end - bmap->start) / 8) + 1;
- new_size = ((new_real_end - bmap->start) / 8) + 1;
-
- if (size != new_size) {
- retval = ext2fs_resize_mem(size, new_size, &bmap->bitmap);
- if (retval)
- return retval;
- }
- if (new_size > size)
- memset(bmap->bitmap + size, 0, new_size - size);
-
- bmap->end = new_end;
- bmap->real_end = new_real_end;
- return 0;
-}
-
-errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
- ext2fs_inode_bitmap bmap)
-{
- errcode_t retval;
-
- if (!bmap)
- return EXT2_ET_INVALID_ARGUMENT;
-
- EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_INODE_BITMAP);
-
- bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
- retval = ext2fs_resize_generic_bitmap(new_end, new_real_end,
- bmap);
- bmap->magic = EXT2_ET_MAGIC_INODE_BITMAP;
- return retval;
-}
-
-errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
- ext2fs_block_bitmap bmap)
-{
- errcode_t retval;
-
- if (!bmap)
- return EXT2_ET_INVALID_ARGUMENT;
-
- EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_BLOCK_BITMAP);
-
- bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
- retval = ext2fs_resize_generic_bitmap(new_end, new_real_end,
- bmap);
- bmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP;
- return retval;
-}
-
diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c
index cb470b8..dd5dc46 100644
--- a/lib/ext2fs/rw_bitmaps.c
+++ b/lib/ext2fs/rw_bitmaps.c
@@ -27,30 +27,6 @@
#include "ext2fs.h"
#include "e2image.h"
-#if defined(__powerpc__) && defined(EXT2FS_ENABLE_SWAPFS)
-/*
- * On the PowerPC, the big-endian variant of the ext2 filesystem
- * has its bitmaps stored as 32-bit words with bit 0 as the LSB
- * of each word. Thus a bitmap with only bit 0 set would be, as
- * a string of bytes, 00 00 00 01 00 ...
- * To cope with this, we byte-reverse each word of a bitmap if
- * we have a big-endian filesystem, that is, if we are *not*
- * byte-swapping other word-sized numbers.
- */
-#define EXT2_BIG_ENDIAN_BITMAPS
-#endif
-
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
-static void ext2fs_swap_bitmap(ext2_filsys fs, char *bitmap, int nbytes)
-{
- __u32 *p = (__u32 *) bitmap;
- int n;
-
- for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
- *p = ext2fs_swab32(*p);
-}
-#endif
-
static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
{
dgrp_t i;
@@ -58,10 +34,11 @@
int block_nbytes, inode_nbytes;
unsigned int nbits;
errcode_t retval;
- char *block_bitmap, *inode_bitmap;
char *block_buf, *inode_buf;
int lazy_flag = 0;
blk_t blk;
+ blk_t blk_itr = fs->super->s_first_data_block;
+ ext2_ino_t ino_itr = 1;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
@@ -71,9 +48,7 @@
EXT2_FEATURE_COMPAT_LAZY_BG))
lazy_flag = 1;
inode_nbytes = block_nbytes = 0;
- block_bitmap = inode_bitmap = 0;
if (do_block) {
- block_bitmap = fs->block_map->bitmap;
block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
retval = ext2fs_get_mem(fs->blocksize, &block_buf);
if (retval)
@@ -81,7 +56,6 @@
memset(block_buf, 0xff, fs->blocksize);
}
if (do_inode) {
- inode_bitmap = fs->inode_map->bitmap;
inode_nbytes = (size_t)
((EXT2_INODES_PER_GROUP(fs->super)+7) / 8);
retval = ext2fs_get_mem(fs->blocksize, &inode_buf);
@@ -91,14 +65,18 @@
}
for (i = 0; i < fs->group_desc_count; i++) {
- if (!block_bitmap || !do_block)
+ if (!do_block)
goto skip_block_bitmap;
if (lazy_flag && fs->group_desc[i].bg_flags &
EXT2_BG_BLOCK_UNINIT)
goto skip_this_block_bitmap;
- memcpy(block_buf, block_bitmap, block_nbytes);
+ retval = ext2fs_get_block_bitmap_range(fs->block_map,
+ blk_itr, block_nbytes << 3, block_buf);
+ if (retval)
+ return retval;
+
if (i == fs->group_desc_count - 1) {
/* Force bitmap padding for the last group */
nbits = ((fs->super->s_blocks_count
@@ -110,44 +88,36 @@
}
blk = fs->group_desc[i].bg_block_bitmap;
if (blk) {
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
- if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
- ext2fs_swap_bitmap(fs, block_buf,
- block_nbytes);
-#endif
retval = io_channel_write_blk(fs->io, blk, 1,
block_buf);
if (retval)
return EXT2_ET_BLOCK_BITMAP_WRITE;
}
skip_this_block_bitmap:
- block_bitmap += block_nbytes;
+ blk_itr += block_nbytes << 3;
skip_block_bitmap:
- if (!inode_bitmap || !do_inode)
+ if (!do_inode)
continue;
if (lazy_flag && fs->group_desc[i].bg_flags &
EXT2_BG_INODE_UNINIT)
goto skip_this_inode_bitmap;
- memcpy(inode_buf, inode_bitmap, inode_nbytes);
+ retval = ext2fs_get_inode_bitmap_range(fs->inode_map,
+ ino_itr, inode_nbytes << 3, inode_buf);
+ if (retval)
+ return retval;
+
blk = fs->group_desc[i].bg_inode_bitmap;
if (blk) {
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
- if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
- ext2fs_swap_bitmap(fs, inode_buf,
- inode_nbytes);
-#endif
retval = io_channel_write_blk(fs->io, blk, 1,
inode_buf);
if (retval)
return EXT2_ET_INODE_BITMAP_WRITE;
}
skip_this_inode_bitmap:
- inode_bitmap += inode_nbytes;
+ ino_itr += inode_nbytes << 3;
}
if (do_block) {
@@ -167,17 +137,25 @@
char *block_bitmap = 0, *inode_bitmap = 0;
char *buf;
errcode_t retval;
- int block_nbytes = (int) EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
- int inode_nbytes = (int) EXT2_INODES_PER_GROUP(fs->super) / 8;
+ unsigned int block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
+ unsigned inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
int lazy_flag = 0;
+ int do_image = fs->flags & EXT2_FLAG_IMAGE_FILE;
+ unsigned int cnt;
blk_t blk;
+ blk_t blk_itr = fs->super->s_first_data_block;
+ blk_t blk_cnt;
+ ext2_ino_t ino_itr = 1;
+ ext2_ino_t ino_cnt;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
fs->write_bitmaps = ext2fs_write_bitmaps;
- if (EXT2_HAS_COMPAT_FEATURE(fs->super,
- EXT2_FEATURE_COMPAT_LAZY_BG))
+ if (EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_LAZY_BG) ||
+ EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
lazy_flag = 1;
retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
@@ -190,8 +168,12 @@
retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
if (retval)
goto cleanup;
- block_bitmap = fs->block_map->bitmap;
- }
+ retval = ext2fs_get_mem(do_image ? fs->blocksize :
+ block_nbytes, &block_bitmap);
+ if (retval)
+ goto cleanup;
+ } else
+ block_nbytes = 0;
if (do_inode) {
if (fs->inode_map)
ext2fs_free_inode_bitmap(fs->inode_map);
@@ -199,37 +181,62 @@
retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
if (retval)
goto cleanup;
- inode_bitmap = fs->inode_map->bitmap;
- }
+ retval = ext2fs_get_mem(do_image ? fs->blocksize :
+ inode_nbytes, &inode_bitmap);
+ if (retval)
+ goto cleanup;
+ } else
+ inode_nbytes = 0;
ext2fs_free_mem(&buf);
if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
- if (inode_bitmap) {
- blk = (fs->image_header->offset_inodemap /
- fs->blocksize);
- retval = io_channel_read_blk(fs->image_io, blk,
- -(inode_nbytes * fs->group_desc_count),
- inode_bitmap);
+ blk = (fs->image_header->offset_inodemap / fs->blocksize);
+ ino_cnt = fs->super->s_inodes_count;
+ while (inode_nbytes > 0) {
+ retval = io_channel_read_blk(fs->image_io, blk++,
+ 1, inode_bitmap);
if (retval)
goto cleanup;
- }
- if (block_bitmap) {
- blk = (fs->image_header->offset_blockmap /
- fs->blocksize);
- retval = io_channel_read_blk(fs->image_io, blk,
- -(block_nbytes * fs->group_desc_count),
- block_bitmap);
+ cnt = fs->blocksize << 3;
+ if (cnt > ino_cnt)
+ cnt = ino_cnt;
+ retval = ext2fs_set_inode_bitmap_range(fs->inode_map,
+ ino_itr, cnt, inode_bitmap);
if (retval)
goto cleanup;
+ ino_itr += fs->blocksize << 3;
+ ino_cnt -= fs->blocksize << 3;
+ inode_nbytes -= fs->blocksize;
}
- return 0;
+ blk = (fs->image_header->offset_blockmap /
+ fs->blocksize);
+ blk_cnt = EXT2_BLOCKS_PER_GROUP(fs->super) *
+ fs->group_desc_count;
+ while (block_nbytes > 0) {
+ retval = io_channel_read_blk(fs->image_io, blk++,
+ 1, block_bitmap);
+ if (retval)
+ goto cleanup;
+ cnt = fs->blocksize << 3;
+ if (cnt > blk_cnt)
+ cnt = blk_cnt;
+ retval = ext2fs_set_block_bitmap_range(fs->block_map,
+ blk_itr, cnt, block_bitmap);
+ if (retval)
+ goto cleanup;
+ blk_itr += fs->blocksize << 3;
+ blk_cnt -= fs->blocksize << 3;
+ block_nbytes -= fs->blocksize;
+ }
+ goto success_cleanup;
}
for (i = 0; i < fs->group_desc_count; i++) {
if (block_bitmap) {
blk = fs->group_desc[i].bg_block_bitmap;
if (lazy_flag && fs->group_desc[i].bg_flags &
- EXT2_BG_BLOCK_UNINIT)
+ EXT2_BG_BLOCK_UNINIT &&
+ ext2fs_group_desc_csum_verify(fs, i))
blk = 0;
if (blk) {
retval = io_channel_read_blk(fs->io, blk,
@@ -238,19 +245,20 @@
retval = EXT2_ET_BLOCK_BITMAP_READ;
goto cleanup;
}
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
- if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
- ext2fs_swap_bitmap(fs, block_bitmap, block_nbytes);
-#endif
} else
memset(block_bitmap, 0xff, block_nbytes);
- block_bitmap += block_nbytes;
+ cnt = block_nbytes << 3;
+ retval = ext2fs_set_block_bitmap_range(fs->block_map,
+ blk_itr, cnt, block_bitmap);
+ if (retval)
+ goto cleanup;
+ blk_itr += block_nbytes << 3;
}
if (inode_bitmap) {
blk = fs->group_desc[i].bg_inode_bitmap;
if (lazy_flag && fs->group_desc[i].bg_flags &
- EXT2_BG_INODE_UNINIT)
+ EXT2_BG_INODE_UNINIT &&
+ ext2fs_group_desc_csum_verify(fs, i))
blk = 0;
if (blk) {
retval = io_channel_read_blk(fs->io, blk,
@@ -259,16 +267,21 @@
retval = EXT2_ET_INODE_BITMAP_READ;
goto cleanup;
}
-#ifdef EXT2_BIG_ENDIAN_BITMAPS
- if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
- (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
- ext2fs_swap_bitmap(fs, inode_bitmap, inode_nbytes);
-#endif
} else
memset(inode_bitmap, 0xff, inode_nbytes);
- inode_bitmap += inode_nbytes;
+ cnt = inode_nbytes << 3;
+ retval = ext2fs_set_inode_bitmap_range(fs->inode_map,
+ ino_itr, cnt, inode_bitmap);
+ if (retval)
+ goto cleanup;
+ ino_itr += inode_nbytes << 3;
}
}
+success_cleanup:
+ if (inode_bitmap)
+ ext2fs_free_mem(&inode_bitmap);
+ if (block_bitmap)
+ ext2fs_free_mem(&block_bitmap);
return 0;
cleanup:
@@ -280,6 +293,10 @@
ext2fs_free_mem(&fs->inode_map);
fs->inode_map = 0;
}
+ if (inode_bitmap)
+ ext2fs_free_mem(&inode_bitmap);
+ if (block_bitmap)
+ ext2fs_free_mem(&block_bitmap);
if (buf)
ext2fs_free_mem(&buf);
return retval;
diff --git a/lib/ext2fs/swapfs.c b/lib/ext2fs/swapfs.c
index e07e87c..33c7ab3 100644
--- a/lib/ext2fs/swapfs.c
+++ b/lib/ext2fs/swapfs.c
@@ -20,7 +20,7 @@
#include "ext2fs.h"
#include <ext2fs/ext2_ext_attr.h>
-#ifdef EXT2FS_ENABLE_SWAPFS
+#ifdef WORDS_BIGENDIAN
void ext2fs_swap_super(struct ext2_super_block * sb)
{
int i;
@@ -90,6 +90,29 @@
gdp->bg_checksum = ext2fs_swab16(gdp->bg_checksum);
}
+void ext2fs_swap_ext_attr_header(struct ext2_ext_attr_header *to_header,
+ struct ext2_ext_attr_header *from_header)
+{
+ int n;
+
+ to_header->h_magic = ext2fs_swab32(from_header->h_magic);
+ to_header->h_blocks = ext2fs_swab32(from_header->h_blocks);
+ to_header->h_refcount = ext2fs_swab32(from_header->h_refcount);
+ to_header->h_hash = ext2fs_swab32(from_header->h_hash);
+ for (n = 0; n < 4; n++)
+ to_header->h_reserved[n] =
+ ext2fs_swab32(from_header->h_reserved[n]);
+}
+
+void ext2fs_swap_ext_attr_entry(struct ext2_ext_attr_entry *to_entry,
+ struct ext2_ext_attr_entry *from_entry)
+{
+ to_entry->e_value_offs = ext2fs_swab16(from_entry->e_value_offs);
+ to_entry->e_value_block = ext2fs_swab32(from_entry->e_value_block);
+ to_entry->e_value_size = ext2fs_swab32(from_entry->e_value_size);
+ to_entry->e_hash = ext2fs_swab32(from_entry->e_hash);
+}
+
void ext2fs_swap_ext_attr(char *to, char *from, int bufsize, int has_header)
{
struct ext2_ext_attr_header *from_header =
@@ -98,32 +121,22 @@
(struct ext2_ext_attr_header *)to;
struct ext2_ext_attr_entry *from_entry, *to_entry;
char *from_end = (char *)from_header + bufsize;
- int n;
if (to_header != from_header)
memcpy(to_header, from_header, bufsize);
- from_entry = (struct ext2_ext_attr_entry *)from_header;
- to_entry = (struct ext2_ext_attr_entry *)to_header;
-
if (has_header) {
- to_header->h_magic = ext2fs_swab32(from_header->h_magic);
- to_header->h_blocks = ext2fs_swab32(from_header->h_blocks);
- to_header->h_refcount = ext2fs_swab32(from_header->h_refcount);
- for (n=0; n<4; n++)
- to_header->h_reserved[n] =
- ext2fs_swab32(from_header->h_reserved[n]);
+ ext2fs_swap_ext_attr_header(to_header, from_header);
+
from_entry = (struct ext2_ext_attr_entry *)(from_header+1);
to_entry = (struct ext2_ext_attr_entry *)(to_header+1);
+ } else {
+ from_entry = (struct ext2_ext_attr_entry *)from_header;
+ to_entry = (struct ext2_ext_attr_entry *)to_header;
}
while ((char *)from_entry < from_end && *(__u32 *)from_entry) {
- to_entry->e_value_offs =
- ext2fs_swab16(from_entry->e_value_offs);
- to_entry->e_value_block =
- ext2fs_swab32(from_entry->e_value_block);
- to_entry->e_value_size =
- ext2fs_swab32(from_entry->e_value_size);
+ ext2fs_swap_ext_attr_entry(to_entry, from_entry);
from_entry = EXT2_EXT_ATTR_NEXT(from_entry);
to_entry = EXT2_EXT_ATTR_NEXT(to_entry);
}
@@ -134,6 +147,7 @@
int bufsize)
{
unsigned i, has_data_blocks, extra_isize, attr_magic;
+ int has_extents = 0;
int islnk = 0;
__u32 *eaf, *eat;
@@ -158,9 +172,14 @@
if (!hostorder)
has_data_blocks = ext2fs_inode_data_blocks(fs,
(struct ext2_inode *) t);
+ if (hostorder && (f->i_flags & EXT4_EXTENTS_FL))
+ has_extents = 1;
t->i_flags = ext2fs_swab32(f->i_flags);
+ if (!hostorder && (t->i_flags & EXT4_EXTENTS_FL))
+ has_extents = 1;
t->i_dir_acl = ext2fs_swab32(f->i_dir_acl);
- if (!islnk || has_data_blocks ) {
+ /* extent data are swapped on access, not here */
+ if (!has_extents && (!islnk || has_data_blocks)) {
for (i = 0; i < EXT2_N_BLOCKS; i++)
t->i_block[i] = ext2fs_swab32(f->i_block[i]);
} else if (t != f) {
@@ -198,16 +217,7 @@
t->osd2.hurd2.h_i_author =
ext2fs_swab32 (f->osd2.hurd2.h_i_author);
break;
- case EXT2_OS_MASIX:
- t->osd1.masix1.m_i_reserved1 =
- ext2fs_swab32(f->osd1.masix1.m_i_reserved1);
- t->osd2.masix2.m_i_frag = f->osd2.masix2.m_i_frag;
- t->osd2.masix2.m_i_fsize = f->osd2.masix2.m_i_fsize;
- t->osd2.masix2.m_pad1 = ext2fs_swab16(f->osd2.masix2.m_pad1);
- t->osd2.masix2.m_i_reserved2[0] =
- ext2fs_swab32(f->osd2.masix2.m_i_reserved2[0]);
- t->osd2.masix2.m_i_reserved2[1] =
- ext2fs_swab32(f->osd2.masix2.m_i_reserved2[1]);
+ default:
break;
}
diff --git a/lib/ext2fs/test_io.c b/lib/ext2fs/test_io.c
index 03d63ce..2fe10d2 100644
--- a/lib/ext2fs/test_io.c
+++ b/lib/ext2fs/test_io.c
@@ -66,6 +66,8 @@
int count, const void *buf);
static errcode_t test_set_option(io_channel channel, const char *option,
const char *arg);
+static errcode_t test_get_stats(io_channel channel, io_stats *stats);
+
static struct struct_io_manager struct_test_manager = {
EXT2_ET_MAGIC_IO_MANAGER,
@@ -77,7 +79,8 @@
test_write_blk,
test_flush,
test_write_byte,
- test_set_option
+ test_set_option,
+ test_get_stats,
};
io_manager test_io_manager = &struct_test_manager;
@@ -409,3 +412,18 @@
}
return retval;
}
+
+static errcode_t test_get_stats(io_channel channel, io_stats *stats)
+{
+ struct test_private_data *data;
+ errcode_t retval = 0;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct test_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+ if (data->real && data->real->manager->get_stats) {
+ retval = (data->real->manager->get_stats)(data->real, stats);
+ }
+ return retval;
+}
diff --git a/lib/ext2fs/tst_csum.c b/lib/ext2fs/tst_csum.c
new file mode 100644
index 0000000..eb7377d
--- /dev/null
+++ b/lib/ext2fs/tst_csum.c
@@ -0,0 +1,127 @@
+/*
+ * This testing program verifies checksumming operations
+ *
+ * Copyright (C) 2006, 2007 by Andreas Dilger <adilger@clusterfs.com>
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU General Public
+ * License, Version 2. See the file COPYING for more details.
+ * %End-Header%
+ */
+
+#include "ext2fs/ext2_fs.h"
+#include "ext2fs/ext2fs.h"
+
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+void print_csum(const char *msg, ext2_filsys fs, dgrp_t group)
+{
+ __u16 crc1, crc2, crc3;
+ dgrp_t swabgroup;
+ struct ext2_group_desc *desc = &fs->group_desc[group];
+ struct ext2_super_block *sb = fs->super;
+
+#ifdef WORDS_BIGENDIAN
+ struct ext2_group_desc swabdesc = fs->group_desc[group];
+
+ /* Have to swab back to little-endian to do the checksum */
+ ext2fs_swap_group_desc(&swabdesc);
+ desc = &swabdesc;
+
+ swabgroup = ext2fs_swab32(group);
+#else
+ swabgroup = group;
+#endif
+
+ crc1 = crc16(~0, sb->s_uuid, sizeof(fs->super->s_uuid));
+ crc2 = crc16(crc1, &swabgroup, sizeof(swabgroup));
+ crc3 = crc16(crc2, desc, offsetof(struct ext2_group_desc, bg_checksum));
+ printf("%s: UUID %016Lx%016Lx(%04x), grp %u(%04x): %04x=%04x\n",
+ msg, *(long long *)&sb->s_uuid, *(long long *)&sb->s_uuid[8],
+ crc1, group, crc2, crc3, ext2fs_group_desc_csum(fs, group));
+}
+
+unsigned char sb_uuid[16] = { 0x4f, 0x25, 0xe8, 0xcf, 0xe7, 0x97, 0x48, 0x23,
+ 0xbe, 0xfa, 0xa7, 0x88, 0x4b, 0xae, 0xec, 0xdb };
+
+main(int argc, char **argv)
+{
+ struct ext2_super_block param;
+ errcode_t retval;
+ ext2_filsys fs;
+ int i;
+ __u16 csum1, csum2, csum_known = 0xd3a4;
+
+ memset(¶m, 0, sizeof(param));
+ param.s_blocks_count = 32768;
+
+ retval = ext2fs_initialize("test fs", 0, ¶m,
+ test_io_manager, &fs);
+ if (retval) {
+ com_err("setup", retval,
+ "While initializing filesystem");
+ exit(1);
+ }
+ memcpy(fs->super->s_uuid, sb_uuid, 16);
+ fs->super->s_feature_ro_compat = EXT4_FEATURE_RO_COMPAT_GDT_CSUM;
+
+ for (i=0; i < fs->group_desc_count; i++) {
+ fs->group_desc[i].bg_block_bitmap = 124;
+ fs->group_desc[i].bg_inode_bitmap = 125;
+ fs->group_desc[i].bg_inode_table = 126;
+ fs->group_desc[i].bg_free_blocks_count = 31119;
+ fs->group_desc[i].bg_free_inodes_count = 15701;
+ fs->group_desc[i].bg_used_dirs_count = 2;
+ fs->group_desc[i].bg_flags = 0;
+ };
+
+ csum1 = ext2fs_group_desc_csum(fs, 0);
+ print_csum("csum0000", fs, 0);
+
+ if (csum1 != csum_known) {
+ printf("checksum for group 0 should be %04x\n", csum_known);
+ exit(1);
+ }
+ csum2 = ext2fs_group_desc_csum(fs, 1);
+ print_csum("csum0001", fs, 1);
+ if (csum1 == csum2) {
+ printf("checksums for different groups shouldn't match\n");
+ exit(1);
+ }
+ csum2 = ext2fs_group_desc_csum(fs, 2);
+ print_csum("csumffff", fs, 2);
+ if (csum1 == csum2) {
+ printf("checksums for different groups shouldn't match\n");
+ exit(1);
+ }
+ fs->group_desc[0].bg_checksum = csum1;
+ csum2 = ext2fs_group_desc_csum(fs, 0);
+ print_csum("csum_set", fs, 0);
+ if (csum1 != csum2) {
+ printf("checksums should not depend on checksum field\n");
+ exit(1);
+ }
+ if (!ext2fs_group_desc_csum_verify(fs, 0)) {
+ printf("checksums should verify against gd_checksum\n");
+ exit(1);
+ }
+ memset(fs->super->s_uuid, 0x30, sizeof(fs->super->s_uuid));
+ print_csum("new_uuid", fs, 0);
+ if (ext2fs_group_desc_csum_verify(fs, 0) != 0) {
+ printf("checksums for different filesystems shouldn't match\n");
+ exit(1);
+ }
+ csum1 = fs->group_desc[0].bg_checksum = ext2fs_group_desc_csum(fs, 0);
+ print_csum("csum_new", fs, 0);
+ fs->group_desc[0].bg_free_blocks_count = 1;
+ csum2 = ext2fs_group_desc_csum(fs, 0);
+ print_csum("csum_blk", fs, 0);
+ if (csum1 == csum2) {
+ printf("checksums for different data shouldn't match\n");
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c
index 4ede000..eedbcdb 100644
--- a/lib/ext2fs/unix_io.c
+++ b/lib/ext2fs/unix_io.c
@@ -70,6 +70,7 @@
int access_time;
ext2_loff_t offset;
struct unix_cache cache[CACHE_SIZE];
+ struct struct_io_stats io_stats;
};
static errcode_t unix_open(const char *name, int flags, io_channel *channel);
@@ -84,9 +85,14 @@
int size, const void *data);
static errcode_t unix_set_option(io_channel channel, const char *option,
const char *arg);
-
+static errcode_t unix_get_stats(io_channel channel, io_stats *stats)
+;
static void reuse_cache(io_channel channel, struct unix_private_data *data,
- struct unix_cache *cache, unsigned long block);
+ struct unix_cache *cache, unsigned long long block);
+static errcode_t unix_read_blk64(io_channel channel, unsigned long long block,
+ int count, void *data);
+static errcode_t unix_write_blk64(io_channel channel, unsigned long long block,
+ int count, const void *data);
/* __FreeBSD_kernel__ is defined by GNU/kFreeBSD - the FreeBSD kernel
* does not know buffered block devices - everything is raw. */
@@ -110,18 +116,37 @@
#else
unix_write_byte,
#endif
- unix_set_option
+ unix_set_option,
+ unix_get_stats,
+ unix_read_blk64,
+ unix_write_blk64,
};
io_manager unix_io_manager = &struct_unix_manager;
+static errcode_t unix_get_stats(io_channel channel, io_stats *stats)
+{
+ errcode_t retval = 0;
+
+ struct unix_private_data *data;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct unix_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
+
+ if (stats)
+ *stats = &data->io_stats;
+
+ return retval;
+}
+
/*
* Here are the raw I/O functions
*/
#ifndef NEED_BOUNCE_BUFFER
static errcode_t raw_read_blk(io_channel channel,
struct unix_private_data *data,
- unsigned long block,
+ unsigned long long block,
int count, void *buf)
{
errcode_t retval;
@@ -130,6 +155,7 @@
int actual = 0;
size = (count < 0) ? -count : count * channel->block_size;
+ data->io_stats.bytes_read += size;
location = ((ext2_loff_t) block * channel->block_size) + data->offset;
if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
@@ -168,6 +194,7 @@
char sector[BLOCKALIGN];
size = (count < 0) ? -count : count * channel->block_size;
+ data->io_stats.bytes_read += size;
location = ((ext2_loff_t) block * channel->block_size) + data->offset;
#ifdef DEBUG
printf("count=%d, size=%d, block=%lu, blk_size=%d, location=%llx\n",
@@ -208,7 +235,7 @@
static errcode_t raw_write_blk(io_channel channel,
struct unix_private_data *data,
- unsigned long block,
+ unsigned long long block,
int count, const void *buf)
{
ssize_t size;
@@ -224,6 +251,7 @@
else
size = count * channel->block_size;
}
+ data->io_stats.bytes_written += size;
location = ((ext2_loff_t) block * channel->block_size) + data->offset;
if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
@@ -296,7 +324,7 @@
* entry to that should be reused.
*/
static struct unix_cache *find_cached_block(struct unix_private_data *data,
- unsigned long block,
+ unsigned long long block,
struct unix_cache **eldest)
{
struct unix_cache *cache, *unused_cache, *oldest_cache;
@@ -326,7 +354,7 @@
* Reuse a particular cache entry for another block.
*/
static void reuse_cache(io_channel channel, struct unix_private_data *data,
- struct unix_cache *cache, unsigned long block)
+ struct unix_cache *cache, unsigned long long block)
{
if (cache->dirty && cache->in_use)
raw_write_blk(channel, data, cache->block, 1, cache->buf);
@@ -407,6 +435,7 @@
memset(data, 0, sizeof(struct unix_private_data));
data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL;
+ data->io_stats.num_fields = 2;
if ((retval = alloc_cache(io, data)))
goto cleanup;
@@ -522,7 +551,7 @@
}
-static errcode_t unix_read_blk(io_channel channel, unsigned long block,
+static errcode_t unix_read_blk64(io_channel channel, unsigned long long block,
int count, void *buf)
{
struct unix_private_data *data;
@@ -587,7 +616,13 @@
#endif /* NO_IO_CACHE */
}
-static errcode_t unix_write_blk(io_channel channel, unsigned long block,
+static errcode_t unix_read_blk(io_channel channel, unsigned long block,
+ int count, void *buf)
+{
+ return unix_read_blk64(channel, block, count, buf);
+}
+
+static errcode_t unix_write_blk64(io_channel channel, unsigned long long block,
int count, const void *buf)
{
struct unix_private_data *data;
@@ -639,6 +674,12 @@
#endif /* NO_IO_CACHE */
}
+static errcode_t unix_write_blk(io_channel channel, unsigned long block,
+ int count, const void *buf)
+{
+ return unix_write_blk64(channel, block, count, buf);
+}
+
static errcode_t unix_write_byte(io_channel channel, unsigned long offset,
int size, const void *buf)
{
diff --git a/lib/ss/ss.pc.in b/lib/ss/ss.pc.in
index 0218fd5..ce284fc 100644
--- a/lib/ss/ss.pc.in
+++ b/lib/ss/ss.pc.in
@@ -8,4 +8,5 @@
Version: @E2FSPROGS_VERSION@
Requires: com_err
Cflags: -I${includedir}
-Libs: -L${libdir} -lss @DLOPEN_LIB@
+Libs: -L${libdir} -lss
+Libs.private: @DLOPEN_LIB@
diff --git a/misc/Makefile.in b/misc/Makefile.in
index b4c39ee..bf04e65 100644
--- a/misc/Makefile.in
+++ b/misc/Makefile.in
@@ -80,7 +80,7 @@
default_profile.c: $(srcdir)/mke2fs.conf $(srcdir)/profile-to-c.awk
@echo " PROFILE_TO_C mke2fs.conf"
- $(AWK) -f $(srcdir)/profile-to-c.awk < $(srcdir)/mke2fs.conf \
+ @$(AWK) -f $(srcdir)/profile-to-c.awk < $(srcdir)/mke2fs.conf \
> default_profile.c
profile.o:
@echo " CC $<"
diff --git a/misc/badblocks.c b/misc/badblocks.c
index 88c5a74..709effe 100644
--- a/misc/badblocks.c
+++ b/misc/badblocks.c
@@ -67,13 +67,13 @@
static int force = 0; /* force check of mounted device */
static int t_flag = 0; /* number of test patterns */
static int t_max = 0; /* allocated test patterns */
-static unsigned long *t_patts = NULL; /* test patterns */
+static unsigned int *t_patts = NULL; /* test patterns */
static int current_O_DIRECT = 0; /* Current status of O_DIRECT flag */
static int exclusive_ok = 0;
#define T_INC 32
-int sys_page_size = 4096;
+unsigned int sys_page_size = 4096;
static void usage(void)
{
@@ -90,8 +90,8 @@
exit(1);
}
-static unsigned long currently_testing = 0;
-static unsigned long num_blocks = 0;
+static blk_t currently_testing = 0;
+static blk_t num_blocks = 0;
static ext2_badblocks_list bb_list = NULL;
static FILE *out;
static blk_t next_bad = 0;
@@ -124,14 +124,14 @@
* This routine reports a new bad block. If the bad block has already
* been seen before, then it returns 0; otherwise it returns 1.
*/
-static int bb_output (unsigned long bad)
+static int bb_output (blk_t bad)
{
errcode_t errcode;
if (ext2fs_badblocks_list_test(bb_list, bad))
return 0;
- fprintf(out, "%lu\n", bad);
+ fprintf(out, "%lu\n", (unsigned long) bad);
fflush(out);
errcode = ext2fs_badblocks_list_add (bb_list, bad);
@@ -151,7 +151,8 @@
static void print_status(void)
{
- fprintf(stderr, "%15ld/%15ld", currently_testing, num_blocks);
+ fprintf(stderr, "%15lu/%15lu", (unsigned long) currently_testing,
+ (unsigned long) num_blocks);
fputs("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", stderr);
fflush (stderr);
}
@@ -197,7 +198,7 @@
}
static void set_o_direct(int dev, unsigned char *buffer, size_t size,
- unsigned long current_block)
+ blk_t current_block)
{
#ifdef O_DIRECT
int new_flag = O_DIRECT;
@@ -221,13 +222,13 @@
}
-static void pattern_fill(unsigned char *buffer, unsigned long pattern,
+static void pattern_fill(unsigned char *buffer, unsigned int pattern,
size_t n)
{
unsigned int i, nb;
unsigned char bpattern[sizeof(pattern)], *ptr;
- if (pattern == (unsigned long) ~0) {
+ if (pattern == (unsigned int) ~0) {
for (ptr = buffer; ptr < buffer + n; ptr++) {
(*ptr) = random() % (1 << (8 * sizeof(char)));
}
@@ -262,8 +263,8 @@
* Perform a read of a sequence of blocks; return the number of blocks
* successfully sequentially read.
*/
-static long do_read (int dev, unsigned char * buffer, int try, int block_size,
- unsigned long current_block)
+static int do_read (int dev, unsigned char * buffer, int try, int block_size,
+ blk_t current_block)
{
long got;
@@ -291,8 +292,8 @@
* Perform a write of a sequence of blocks; return the number of blocks
* successfully sequentially written.
*/
-static long do_write (int dev, unsigned char * buffer, int try, int block_size,
- unsigned long current_block)
+static int do_write(int dev, unsigned char * buffer, int try, int block_size,
+ unsigned long current_block)
{
long got;
@@ -327,13 +328,13 @@
com_err(program_name, retval, _("during ext2fs_sync_device"));
}
-static unsigned int test_ro (int dev, unsigned long last_block,
- int block_size, unsigned long from_count,
- unsigned long blocks_at_once)
+static unsigned int test_ro (int dev, blk_t last_block,
+ int block_size, blk_t from_count,
+ unsigned int blocks_at_once)
{
unsigned char * blkbuf;
int try;
- long got;
+ int got;
unsigned int bb_count = 0;
errcode_t errcode;
@@ -358,8 +359,9 @@
exit (1);
}
if (v_flag) {
- fprintf (stderr, _("Checking blocks %lu to %lu\n"), from_count,
- last_block - 1);
+ fprintf (stderr, _("Checking blocks %lu to %lu\n"),
+ (unsigned long) from_count,
+ (unsigned long) last_block - 1);
}
if (t_flag) {
fputs(_("Checking for bad blocks in read-only mode\n"), stderr);
@@ -404,7 +406,7 @@
if (got == try) {
try = blocks_at_once;
/* recover page-aligned offset for O_DIRECT */
- if ( blocks_at_once >= (unsigned long) (sys_page_size >> 9)
+ if ( (blocks_at_once >= sys_page_size >> 9)
&& (currently_testing % (sys_page_size >> 9)!= 0))
try -= (sys_page_size >> 9)
- (currently_testing
@@ -430,13 +432,13 @@
return bb_count;
}
-static unsigned int test_rw (int dev, unsigned long last_block,
- int block_size, unsigned long from_count,
- unsigned long blocks_at_once)
+static unsigned int test_rw (int dev, blk_t last_block,
+ int block_size, blk_t from_count,
+ unsigned int blocks_at_once)
{
unsigned char *buffer, *read_buffer;
- const unsigned long patterns[] = {0xaa, 0x55, 0xff, 0x00};
- const unsigned long *pattern;
+ const unsigned int patterns[] = {0xaa, 0x55, 0xff, 0x00};
+ const unsigned int *pattern;
int i, try, got, nr_pattern, pat_idx;
unsigned int bb_count = 0;
@@ -454,7 +456,8 @@
fputs(_("Checking for bad blocks in read-write mode\n"),
stderr);
fprintf(stderr, _("From block %lu to %lu\n"),
- from_count, last_block);
+ (unsigned long) from_count,
+ (unsigned long) last_block);
}
if (t_flag) {
pattern = t_patts;
@@ -484,7 +487,7 @@
if (got == try) {
try = blocks_at_once;
/* recover page-aligned offset for O_DIRECT */
- if ( blocks_at_once >= (unsigned long) (sys_page_size >> 9)
+ if ( (blocks_at_once >= sys_page_size >> 9)
&& (currently_testing %
(sys_page_size >> 9)!= 0))
try -= (sys_page_size >> 9)
@@ -528,7 +531,7 @@
}
currently_testing += got;
/* recover page-aligned offset for O_DIRECT */
- if ( blocks_at_once >= (unsigned long) (sys_page_size >> 9)
+ if ( (blocks_at_once >= sys_page_size >> 9)
&& (currently_testing % (sys_page_size >> 9)!= 0))
try = blocks_at_once - (sys_page_size >> 9)
- (currently_testing
@@ -555,17 +558,18 @@
int num;
};
-static unsigned int test_nd (int dev, unsigned long last_block,
- int block_size, unsigned long from_count,
- unsigned long blocks_at_once)
+static unsigned int test_nd (int dev, blk_t last_block,
+ int block_size, blk_t from_count,
+ unsigned int blocks_at_once)
{
unsigned char *blkbuf, *save_ptr, *test_ptr, *read_ptr;
unsigned char *test_base, *save_base, *read_base;
int try, i;
- const unsigned long patterns[] = { ~0 };
- const unsigned long *pattern;
+ const unsigned int patterns[] = { ~0 };
+ const unsigned int *pattern;
int nr_pattern, pat_idx;
- long got, used2, written, save_currently_testing;
+ int got, used2, written;
+ blk_t save_currently_testing;
struct saved_blk_record *test_record;
/* This is static to prevent being clobbered by the longjmp */
static int num_saved;
@@ -601,7 +605,8 @@
flush_bufs();
if (v_flag) {
fputs(_("Checking for bad blocks in non-destructive read-write mode\n"), stderr);
- fprintf (stderr, _("From block %lu to %lu\n"), from_count, last_block);
+ fprintf (stderr, _("From block %lu to %lu\n"),
+ (unsigned long) from_count, (unsigned long) last_block);
}
if (s_flag || v_flag > 1) {
fputs(_("Checking for bad blocks (non-destructive read-write test)\n"), stderr);
@@ -682,7 +687,8 @@
if (written != got)
com_err (program_name, errno,
_("during test data write, block %lu"),
- currently_testing + written);
+ (unsigned long) currently_testing +
+ written);
buf_used += got;
save_ptr += got * block_size;
@@ -813,27 +819,43 @@
}
+/*
+ * This function will convert a string to an unsigned long, printing
+ * an error message if it fails, and returning success or failure in err.
+ */
+static unsigned int parse_uint(const char *str, const char *descr)
+{
+ char *tmp;
+ unsigned long ret;
+
+ ret = strtoul(str, &tmp, 0);
+ if (*tmp || errno || (ret > UINT_MAX) ||
+ (ret == ULONG_MAX && errno == ERANGE)) {
+ com_err (program_name, 0, _("invalid %s - %s"), descr, str);
+ exit (1);
+ }
+ return ret;
+}
int main (int argc, char ** argv)
{
int c;
- char * tmp;
char * device_name;
char * host_device_name = NULL;
char * input_file = NULL;
char * output_file = NULL;
FILE * in = NULL;
int block_size = 1024;
- unsigned long blocks_at_once = 64;
+ unsigned int blocks_at_once = 64;
blk_t last_block, from_count;
int num_passes = 0;
int passes_clean = 0;
int dev;
errcode_t errcode;
- unsigned long pattern;
- unsigned int (*test_func)(int, unsigned long,
- int, unsigned long,
- unsigned long);
+ unsigned int pattern;
+ unsigned int (*test_func)(int, blk_t,
+ int, blk_t,
+ unsigned int);
int open_flag = 0;
long sysval;
@@ -865,8 +887,8 @@
while ((c = getopt (argc, argv, "b:fi:o:svwnc:p:h:t:X")) != EOF) {
switch (c) {
case 'b':
- block_size = strtoul (optarg, &tmp, 0);
- if (*tmp || block_size > 4096) {
+ block_size = parse_uint(optarg, "block size");
+ if (block_size > 4096) {
com_err (program_name, 0,
_("bad block size - %s"), optarg);
exit (1);
@@ -900,27 +922,18 @@
w_flag = 2;
break;
case 'c':
- blocks_at_once = strtoul (optarg, &tmp, 0);
- if (*tmp) {
- com_err (program_name, 0,
- "bad simultaneous block count - %s", optarg);
- exit (1);
- }
+ blocks_at_once = parse_uint(optarg, "blocks at once");
break;
case 'p':
- num_passes = strtoul (optarg, &tmp, 0);
- if (*tmp) {
- com_err (program_name, 0,
- "bad number of clean passes - %s", optarg);
- exit (1);
- }
+ num_passes = parse_uint(optarg,
+ "number of clean passes");
break;
case 'h':
host_device_name = optarg;
break;
case 't':
if (t_flag + 1 > t_max) {
- unsigned long *t_patts_new;
+ unsigned int *t_patts_new;
t_patts_new = realloc(t_patts, t_max + T_INC);
if (!t_patts_new) {
@@ -936,14 +949,8 @@
if (!strcmp(optarg, "r") || !strcmp(optarg,"random")) {
t_patts[t_flag++] = ~0;
} else {
- pattern = strtoul(optarg, &tmp, 0);
- if (*tmp) {
- com_err(program_name, 0,
- _("invalid test_pattern: %s\n"),
- optarg);
- exit(1);
- }
- if (pattern == (unsigned long) ~0)
+ pattern = parse_uint(optarg, "test pattern");
+ if (pattern == (unsigned int) ~0)
pattern = 0xffff;
t_patts[t_flag++] = pattern;
}
@@ -962,7 +969,7 @@
"in read-only mode"));
exit(1);
}
- if (t_patts && (t_patts[0] == (unsigned long) ~0)) {
+ if (t_patts && (t_patts[0] == (unsigned int) ~0)) {
com_err(program_name, 0,
_("Random test_pattern is not allowed "
"in read-only mode"));
@@ -989,30 +996,18 @@
}
} else {
errno = 0;
- last_block = strtoul (argv[optind], &tmp, 0);
+ last_block = parse_uint(argv[optind], "last block");
printf("last_block = %d (%s)\n", last_block, argv[optind]);
- if (*tmp || errno ||
- (last_block == ULONG_MAX && errno == ERANGE)) {
- com_err (program_name, 0, _("invalid blocks count - %s"),
- argv[optind]);
- exit (1);
- }
last_block++;
optind++;
}
if (optind <= argc-1) {
errno = 0;
- from_count = strtoul (argv[optind], &tmp, 0);
+ from_count = parse_uint(argv[optind], "start block");
printf("from_count = %d\n", from_count);
- if (*tmp || errno ||
- (from_count == ULONG_MAX && errno == ERANGE)) {
- com_err (program_name, 0, _("invalid starting block - %s"),
- argv[optind]);
- exit (1);
- }
} else from_count = 0;
if (from_count >= last_block) {
- com_err (program_name, 0, _("invalid starting block (%d): must be less than %lu"),
+ com_err (program_name, 0, _("invalid starting block (%lu): must be less than %lu"),
(unsigned long) from_count, (unsigned long) last_block);
exit (1);
}
diff --git a/misc/chattr.1.in b/misc/chattr.1.in
index 2b48fb0..2334675 100644
--- a/misc/chattr.1.in
+++ b/misc/chattr.1.in
@@ -5,7 +5,7 @@
.SH SYNOPSIS
.B chattr
[
-.B \-RV
+.B \-RVf
]
[
.B \-v
@@ -34,12 +34,13 @@
.TP
.B \-R
Recursively change attributes of directories and their contents.
-Symbolic links encountered during recursive directory traversals are
-ignored.
.TP
.B \-V
Be verbose with chattr's output and print the program version.
.TP
+.B \-f
+Suppress most error messages.
+.TP
.BI \-v " version"
Set the file's version/generation number.
.SH ATTRIBUTES
diff --git a/misc/chattr.c b/misc/chattr.c
index c6d8d9f..daae163 100644
--- a/misc/chattr.c
+++ b/misc/chattr.c
@@ -65,6 +65,7 @@
static int recursive;
static int verbose;
+static int silent;
static unsigned long af;
static unsigned long rf;
@@ -80,8 +81,8 @@
static void usage(void)
{
- fprintf(stderr,
- _("Usage: %s [-RV] [-+=AacDdijsSu] [-v version] files...\n"),
+ fprintf(stderr,
+ _("Usage: %s [-RVf] [-+=AacDdijsSu] [-v version] files...\n"),
program_name);
exit(1);
}
@@ -137,6 +138,10 @@
verbose = 1;
continue;
}
+ if (*p == 'f') {
+ silent = 1;
+ continue;
+ }
if (*p == 'v') {
(*i)++;
if (*i >= argc)
@@ -144,7 +149,7 @@
version = strtol (argv[*i], &tmp, 0);
if (*tmp) {
com_err (program_name, 0,
- _("bad version - %s\n"),
+ _("bad version - %s\n"),
argv[*i]);
usage ();
}
@@ -180,28 +185,19 @@
return 1;
}
-static int chattr_dir_proc (const char *, struct dirent *, void *);
+static int chattr_dir_proc(const char *, struct dirent *, void *);
-static void change_attributes (const char * name)
+static int change_attributes(const char * name)
{
unsigned long flags;
STRUCT_STAT st;
if (LSTAT (name, &st) == -1) {
- com_err (program_name, errno, _("while trying to stat %s"),
- name);
- return;
+ if (!silent)
+ com_err (program_name, errno,
+ _("while trying to stat %s"), name);
+ return -1;
}
- if (S_ISLNK(st.st_mode) && recursive)
- return;
-
- /* Don't try to open device files, fifos etc. We probably
- ought to display an error if the file was explicitly given
- on the command line (whether or not recursive was
- requested). */
- if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) &&
- !S_ISDIR(st.st_mode))
- return;
if (set) {
if (verbose) {
@@ -212,10 +208,12 @@
if (fsetflags (name, sf) == -1)
perror (name);
} else {
- if (fgetflags (name, &flags) == -1)
- com_err (program_name, errno,
- _("while reading flags on %s"), name);
- else {
+ if (fgetflags (name, &flags) == -1) {
+ if (!silent)
+ com_err (program_name, errno,
+ _("while reading flags on %s"), name);
+ return -1;
+ } else {
if (rem)
flags &= ~rf;
if (add)
@@ -227,25 +225,36 @@
}
if (!S_ISDIR(st.st_mode))
flags &= ~EXT2_DIRSYNC_FL;
- if (fsetflags (name, flags) == -1)
- com_err (program_name, errno,
- _("while setting flags on %s"), name);
+ if (fsetflags (name, flags) == -1) {
+ if (!silent)
+ com_err(program_name, errno,
+ _("while setting flags on %s"),
+ name);
+ return -1;
+ }
}
}
if (set_version) {
if (verbose)
printf (_("Version of %s set as %lu\n"), name, version);
- if (fsetversion (name, version) == -1)
- com_err (program_name, errno,
- _("while setting version on %s"), name);
+ if (fsetversion (name, version) == -1) {
+ if (!silent)
+ com_err (program_name, errno,
+ _("while setting version on %s"),
+ name);
+ return -1;
+ }
}
if (S_ISDIR(st.st_mode) && recursive)
- iterate_on_dir (name, chattr_dir_proc, NULL);
+ return iterate_on_dir (name, chattr_dir_proc, NULL);
+ return 0;
}
static int chattr_dir_proc (const char * dir_name, struct dirent * de,
void * private EXT2FS_ATTR((unused)))
{
+ int ret = 0;
+
if (strcmp (de->d_name, ".") && strcmp (de->d_name, "..")) {
char *path;
@@ -253,19 +262,20 @@
if (!path) {
fprintf(stderr, _("Couldn't allocate path variable "
"in chattr_dir_proc"));
- exit(1);
+ return -1;
}
- sprintf (path, "%s/%s", dir_name, de->d_name);
- change_attributes (path);
+ sprintf(path, "%s/%s", dir_name, de->d_name);
+ ret = change_attributes(path);
free(path);
}
- return 0;
+ return ret;
}
int main (int argc, char ** argv)
{
int i, j;
int end_arg = 0;
+ int err, retval = 0;
#ifdef ENABLE_NLS
setlocale(LC_MESSAGES, "");
@@ -303,7 +313,10 @@
if (verbose)
fprintf (stderr, "chattr %s (%s)\n",
E2FSPROGS_VERSION, E2FSPROGS_DATE);
- for (j = i; j < argc; j++)
- change_attributes (argv[j]);
- exit(0);
+ for (j = i; j < argc; j++) {
+ err = change_attributes (argv[j]);
+ if (err)
+ retval = 1;
+ }
+ exit(retval);
}
diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c
index 394f8b2..b0bdd7d 100644
--- a/misc/dumpe2fs.c
+++ b/misc/dumpe2fs.c
@@ -112,14 +112,17 @@
{
int first = 1, bg_flags;
- if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_LAZY_BG)
+ if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_LAZY_BG ||
+ fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM)
bg_flags = fs->group_desc[i].bg_flags;
else
bg_flags = 0;
- print_bg_opt(bg_flags, EXT2_BG_INODE_UNINIT, "Inode not init",
+ print_bg_opt(bg_flags, EXT2_BG_INODE_UNINIT, "INODE_UNINIT",
&first);
- print_bg_opt(bg_flags, EXT2_BG_BLOCK_UNINIT, "Block not init",
+ print_bg_opt(bg_flags, EXT2_BG_BLOCK_UNINIT, "BLOCK_UNINIT",
+ &first);
+ print_bg_opt(bg_flags, EXT2_BG_INODE_ZEROED, "ITABLE_ZEROED",
&first);
if (!first)
fputc(']', stdout);
@@ -134,12 +137,18 @@
blk_t super_blk, old_desc_blk, new_desc_blk;
char *block_bitmap=NULL, *inode_bitmap=NULL;
int inode_blocks_per_group, old_desc_blocks, reserved_gdt;
+ int block_nbytes, inode_nbytes;
int has_super;
+ blk_t blk_itr = fs->super->s_first_data_block;
+ ext2_ino_t ino_itr = 1;
+
+ block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
+ inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
if (fs->block_map)
- block_bitmap = fs->block_map->bitmap;
+ block_bitmap = malloc(block_nbytes);
if (fs->inode_map)
- inode_bitmap = fs->inode_map->bitmap;
+ inode_bitmap = malloc(inode_nbytes);
inode_blocks_per_group = ((fs->super->s_inodes_per_group *
EXT2_INODE_SIZE(fs->super)) +
@@ -163,6 +172,10 @@
print_range(first_block, last_block);
fputs(")", stdout);
print_bg_opts(fs, i);
+ if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM)
+ printf(_(" Checksum 0x%04x, unused inodes %d\n"),
+ fs->group_desc[i].bg_checksum,
+ fs->group_desc[i].bg_itable_unused);
has_super = ((i==0) || super_blk);
if (has_super) {
printf (_(" %s superblock at "),
@@ -204,25 +217,33 @@
diff = fs->group_desc[i].bg_inode_table - first_block;
if (diff > 0)
printf(" (+%ld)", diff);
- printf (_("\n %d free blocks, %d free inodes, "
- "%d directories\n"),
+ printf (_("\n %u free blocks, %u free inodes, "
+ "%u directories%s"),
fs->group_desc[i].bg_free_blocks_count,
fs->group_desc[i].bg_free_inodes_count,
- fs->group_desc[i].bg_used_dirs_count);
+ fs->group_desc[i].bg_used_dirs_count,
+ fs->group_desc[i].bg_itable_unused ? "" : "\n");
+ if (fs->group_desc[i].bg_itable_unused)
+ printf (_(", %u unused inodes\n"),
+ fs->group_desc[i].bg_itable_unused);
if (block_bitmap) {
fputs(_(" Free blocks: "), stdout);
+ ext2fs_get_block_bitmap_range(fs->block_map,
+ blk_itr, block_nbytes << 3, block_bitmap);
print_free (i, block_bitmap,
fs->super->s_blocks_per_group,
fs->super->s_first_data_block);
fputc('\n', stdout);
- block_bitmap += fs->super->s_blocks_per_group / 8;
+ blk_itr += fs->super->s_blocks_per_group;
}
if (inode_bitmap) {
fputs(_(" Free inodes: "), stdout);
+ ext2fs_get_inode_bitmap_range(fs->inode_map,
+ ino_itr, inode_nbytes << 3, inode_bitmap);
print_free (i, inode_bitmap,
fs->super->s_inodes_per_group, 1);
fputc('\n', stdout);
- inode_bitmap += fs->super->s_inodes_per_group / 8;
+ ino_itr += fs->super->s_inodes_per_group;
}
}
}
@@ -326,9 +347,9 @@
static void parse_extended_opts(const char *opts, blk_t *superblock,
int *blocksize)
{
- char *buf, *token, *next, *p, *arg, *badopt = "";
+ char *buf, *token, *next, *p, *arg, *badopt = 0;
int len;
- int usage = 0;
+ int do_usage = 0;
len = strlen(opts);
buf = malloc(len+1);
@@ -353,7 +374,7 @@
if (strcmp(token, "superblock") == 0 ||
strcmp(token, "sb") == 0) {
if (!arg) {
- usage++;
+ do_usage++;
badopt = token;
continue;
}
@@ -362,13 +383,13 @@
fprintf(stderr,
_("Invalid superblock parameter: %s\n"),
arg);
- usage++;
+ do_usage++;
continue;
}
} else if (strcmp(token, "blocksize") == 0 ||
strcmp(token, "bs") == 0) {
if (!arg) {
- usage++;
+ do_usage++;
badopt = token;
continue;
}
@@ -377,15 +398,15 @@
fprintf(stderr,
_("Invalid blocksize parameter: %s\n"),
arg);
- usage++;
+ do_usage++;
continue;
}
} else {
- usage++;
+ do_usage++;
badopt = token;
}
}
- if (usage) {
+ if (do_usage) {
fprintf(stderr, _("\nBad extended option(s) specified: %s\n\n"
"Extended options are separated by commas, "
"and may take an argument which\n"
@@ -393,7 +414,7 @@
"Valid extended options are:\n"
"\tsuperblock=<superblock number>\n"
"\tblocksize=<blocksize>\n"),
- badopt);
+ badopt ? badopt : "");
free(buf);
exit(1);
}
@@ -405,13 +426,12 @@
errcode_t retval;
ext2_filsys fs;
int print_badblocks = 0;
- int use_superblock = 0;
+ blk_t use_superblock = 0;
int use_blocksize = 0;
int image_dump = 0;
int force = 0;
int flags;
int header_only = 0;
- int big_endian;
int c;
#ifdef ENABLE_NLS
@@ -488,12 +508,6 @@
if (print_badblocks) {
list_bad_blocks(fs, 1);
} else {
- big_endian = ((fs->flags & EXT2_FLAG_SWAP_BYTES) != 0);
-#ifdef WORDS_BIGENDIAN
- big_endian = !big_endian;
-#endif
- if (big_endian)
- printf(_("Note: This is a byte-swapped filesystem\n"));
list_super (fs->super);
if (fs->super->s_feature_incompat &
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
diff --git a/misc/e2image.c b/misc/e2image.c
index e10554e..081c66f 100644
--- a/misc/e2image.c
+++ b/misc/e2image.c
@@ -347,9 +347,8 @@
for (p = buf; p < end-8; p += rec_len) {
dirent = (struct ext2_dir_entry_2 *) p;
rec_len = dirent->rec_len;
-#ifdef EXT2FS_ENABLE_SWAPFS
- if (fs->flags & EXT2_FLAG_SWAP_BYTES)
- rec_len = ext2fs_swab16(rec_len);
+#ifdef WORDS_BIGENDIAN
+ rec_len = ext2fs_swab16(rec_len);
#endif
#if 0
printf("rec_len = %d, name_len = %d\n", rec_len, dirent->name_len);
@@ -360,8 +359,7 @@
"bad rec_len (%d)\n", (unsigned long) blk,
rec_len);
rec_len = end - p;
-#ifdef EXT2FS_ENABLE_SWAPFS
- if (fs->flags & EXT2_FLAG_SWAP_BYTES)
+#ifdef WORDS_BIGENDIAN
dirent->rec_len = ext2fs_swab16(rec_len);
#endif
continue;
@@ -516,8 +514,9 @@
(LINUX_S_ISLNK(inode.i_mode) &&
ext2fs_inode_has_valid_blocks(&inode)) ||
ino == fs->super->s_journal_inum) {
- retval = ext2fs_block_iterate2(fs, ino, 0,
- block_buf, process_dir_block, &pb);
+ retval = ext2fs_block_iterate2(fs, ino,
+ BLOCK_FLAG_READ_ONLY, block_buf,
+ process_dir_block, &pb);
if (retval) {
com_err(program_name, retval,
"while iterating over inode %u",
@@ -525,11 +524,12 @@
exit(1);
}
} else {
- if (inode.i_block[EXT2_IND_BLOCK] ||
+ if ((inode.i_flags & EXT4_EXTENTS_FL) ||
+ inode.i_block[EXT2_IND_BLOCK] ||
inode.i_block[EXT2_DIND_BLOCK] ||
inode.i_block[EXT2_TIND_BLOCK]) {
retval = ext2fs_block_iterate2(fs,
- ino, 0, block_buf,
+ ino, BLOCK_FLAG_READ_ONLY, block_buf,
process_file_block, &pb);
if (retval) {
com_err(program_name, retval,
diff --git a/misc/fsck.c b/misc/fsck.c
index 139afd0..9510261 100644
--- a/misc/fsck.c
+++ b/misc/fsck.c
@@ -813,7 +813,7 @@
* This function returns true if a particular option appears in a
* comma-delimited options list
*/
-static int opt_in_list(char *opt, char *optlist)
+static int opt_in_list(const char *opt, char *optlist)
{
char *list, *s;
diff --git a/misc/fsck.h b/misc/fsck.h
index 55cb525..8a0f70e 100644
--- a/misc/fsck.h
+++ b/misc/fsck.h
@@ -68,3 +68,6 @@
extern char *base_device(const char *device);
extern const char *identify_fs(const char *fs_name, const char *fs_types);
+
+/* ismounted.h */
+extern int is_mounted(const char *file);
diff --git a/misc/ismounted.c b/misc/ismounted.c
index 72f4cba..94a2d6e 100644
--- a/misc/ismounted.c
+++ b/misc/ismounted.c
@@ -28,6 +28,9 @@
#endif
#include <string.h>
#include <sys/stat.h>
+#include <ctype.h>
+
+#include "fsck.h"
/*
* ext2fs_check_if_mounted flags
@@ -80,7 +83,6 @@
ino_t file_ino=0;
FILE *f;
char buf[1024], *device = 0, *mnt_dir = 0, *cp;
- int fd;
*mount_flags = 0;
if ((f = fopen(mtab_file, "r")) == NULL)
diff --git a/misc/mke2fs.8.in b/misc/mke2fs.8.in
index aaf017d..6cd10b1 100644
--- a/misc/mke2fs.8.in
+++ b/misc/mke2fs.8.in
@@ -438,6 +438,13 @@
@JDEV@must be created with the same
@JDEV@block size as the filesystems that will be using it.
.TP
+.B uninit_groups
+Create a filesystem without initializing all of the groups. This speeds
+up filesystem creation time noticably, and can also reduce
+.BR e2fsck time
+dramatically. This feature is only supported by the ext4 filesystem in
+recent Linux kernels.
+.TP
.B resize_inode
Reserve space so the block group descriptor table may grow in the future.
Useful for online resizing using
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index fc086a4..fd48b83 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -433,6 +433,8 @@
num, blk, error_message(retval));
exit(1);
}
+ /* The kernel doesn't need to zero the itable blocks */
+ fs->group_desc[i].bg_flags |= EXT2_BG_INODE_ZEROED;
}
if (sync_kludge) {
if (sync_kludge == 1)
@@ -448,34 +450,49 @@
static void setup_lazy_bg(ext2_filsys fs)
{
dgrp_t i;
- int blks;
+ int blks, csum_flag;
struct ext2_super_block *sb = fs->super;
struct ext2_group_desc *bg = fs->group_desc;
- if (EXT2_HAS_COMPAT_FEATURE(fs->super,
- EXT2_FEATURE_COMPAT_LAZY_BG)) {
+ csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
+ if (EXT2_HAS_COMPAT_FEATURE(fs->super, EXT2_FEATURE_COMPAT_LAZY_BG) ||
+ csum_flag) {
for (i = 0; i < fs->group_desc_count; i++, bg++) {
if ((i == 0) ||
- (i == fs->group_desc_count-1))
+ (i == fs->group_desc_count - 1 && !csum_flag))
continue;
if (bg->bg_free_inodes_count ==
sb->s_inodes_per_group) {
- bg->bg_free_inodes_count = 0;
bg->bg_flags |= EXT2_BG_INODE_UNINIT;
- sb->s_free_inodes_count -=
- sb->s_inodes_per_group;
+ if (!csum_flag) {
+ bg->bg_free_inodes_count = 0;
+ sb->s_free_inodes_count -=
+ sb->s_inodes_per_group;
+ }
}
+
+ /* Skip groups with GDT backups because the resize
+ * inode has blocks allocated in them, and the last
+ * group because it needs block bitmap padding. */
+ if ((ext2fs_bg_has_super(fs, i) &&
+ sb->s_reserved_gdt_blocks) ||
+ i == fs->group_desc_count - 1)
+ continue;
+
blks = ext2fs_super_and_bgd_loc(fs, i, 0, 0, 0, 0);
- if (bg->bg_free_blocks_count == blks) {
- bg->bg_free_blocks_count = 0;
+ if (bg->bg_free_blocks_count == blks &&
+ bg->bg_flags & EXT2_BG_INODE_UNINIT) {
bg->bg_flags |= EXT2_BG_BLOCK_UNINIT;
- sb->s_free_blocks_count -= blks;
+ if (!csum_flag) {
+ bg->bg_free_blocks_count = 0;
+ sb->s_free_blocks_count -= blks;
+ }
}
}
}
}
-
static void create_root_dir(ext2_filsys fs)
{
errcode_t retval;
@@ -513,11 +530,11 @@
static void create_lost_and_found(ext2_filsys fs)
{
+ unsigned int lpf_size = 0;
errcode_t retval;
ext2_ino_t ino;
const char *name = "lost+found";
int i;
- int lpf_size = 0;
fs->umask = 077;
retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, 0, name);
@@ -535,7 +552,10 @@
}
for (i=1; i < EXT2_NDIR_BLOCKS; i++) {
- if ((lpf_size += fs->blocksize) >= 16*1024)
+ /* Ensure that lost+found is at least 2 blocks, so we always
+ * test large empty blocks for big-block filesystems. */
+ if ((lpf_size += fs->blocksize) >= 16*1024 &&
+ lpf_size >= 2 * fs->blocksize)
break;
retval = ext2fs_expand_dir(fs, ino);
if (retval) {
@@ -694,8 +714,7 @@
if (s->s_reserved_gdt_blocks)
printf(_("Maximum filesystem blocks=%lu\n"),
(s->s_reserved_gdt_blocks + fs->desc_blocks) *
- (fs->blocksize / sizeof(struct ext2_group_desc)) *
- s->s_blocks_per_group);
+ EXT2_DESC_PER_BLOCK(s) * s->s_blocks_per_group);
if (fs->group_desc_count > 1)
printf(_("%u block groups\n"), fs->group_desc_count);
else
@@ -741,8 +760,6 @@
sb->s_creator_os = EXT2_OS_LINUX;
else if (strcasecmp(os, "GNU") == 0 || strcasecmp(os, "hurd") == 0)
sb->s_creator_os = EXT2_OS_HURD;
- else if (strcasecmp(os, "masix") == 0)
- sb->s_creator_os = EXT2_OS_MASIX;
else if (strcasecmp(os, "freebsd") == 0)
sb->s_creator_os = EXT2_OS_FREEBSD;
else if (strcasecmp(os, "lites") == 0)
@@ -757,7 +774,7 @@
static void parse_extended_opts(struct ext2_super_block *param,
const char *opts)
{
- char *buf, *token, *next, *p, *arg, *badopt = "";
+ char *buf, *token, *next, *p, *arg, *badopt = 0;
int len;
int r_usage = 0;
@@ -844,7 +861,7 @@
bpg = param->s_blocks_per_group;
if (!bpg)
bpg = blocksize * 8;
- gdpb = blocksize / sizeof(struct ext2_group_desc);
+ gdpb = EXT2_DESC_PER_BLOCK(param);
group_desc_count =
ext2fs_div_ceil(param->s_blocks_count, bpg);
desc_blocks = (group_desc_count +
@@ -884,7 +901,7 @@
"\tstripe-width=<RAID stride * data disks in blocks>\n"
"\tresize=<resize maximum size in blocks>\n\n"
"\ttest_fs\n"),
- badopt);
+ badopt ? badopt : "");
free(buf);
exit(1);
}
@@ -906,11 +923,14 @@
EXT2_FEATURE_COMPAT_EXT_ATTR,
/* Incompat */
EXT2_FEATURE_INCOMPAT_FILETYPE|
+ EXT3_FEATURE_INCOMPAT_EXTENTS|
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|
- EXT2_FEATURE_INCOMPAT_META_BG,
+ EXT2_FEATURE_INCOMPAT_META_BG|
+ EXT4_FEATURE_INCOMPAT_FLEX_BG,
/* R/O compat */
EXT2_FEATURE_RO_COMPAT_LARGE_FILE|
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
+ EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM
};
@@ -1475,19 +1495,6 @@
}
}
- if (!force && fs_param.s_blocks_count >= ((unsigned) 1 << 31)) {
- com_err(program_name, 0,
- _("Filesystem too large. No more than 2**31-1 blocks\n"
- "\t (8TB using a blocksize of 4k) are currently supported."));
- exit(1);
- }
-
- if ((blocksize > 4096) &&
- (fs_param.s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
- fprintf(stderr, _("\nWarning: some 2.4 kernels do not support "
- "blocksizes greater than 4096\n\tusing ext3. "
- "Use -b 4096 if this is an issue for you.\n\n"));
-
if (inode_size == 0) {
profile_get_integer(profile, "defaults", "inode_size", NULL,
0, &inode_size);
@@ -1506,10 +1513,6 @@
blocksize);
exit(1);
}
- if (inode_size != EXT2_GOOD_OLD_INODE_SIZE)
- fprintf(stderr, _("Warning: %d-byte inodes not usable "
- "on older systems\n"),
- inode_size);
fs_param.s_inode_size = inode_size;
}
@@ -1562,7 +1565,7 @@
errcode_t retval = 0;
ext2_filsys fs;
badblocks_list bb_list = 0;
- int journal_blocks;
+ unsigned int journal_blocks;
unsigned int i;
int val;
io_manager io_ptr;
@@ -1773,7 +1776,7 @@
goto no_journal;
}
if (!quiet) {
- printf(_("Creating journal (%d blocks): "),
+ printf(_("Creating journal (%u blocks): "),
journal_blocks);
fflush(stdout);
}
@@ -1789,6 +1792,14 @@
}
no_journal:
+ if (!super_only) {
+ retval = ext2fs_set_gdt_csum(fs);
+ if (retval) {
+ com_err(program_name, retval,
+ _("\n\twhile setting block group checksum info"));
+ exit(1);
+ }
+ }
if (!quiet)
printf(_("Writing superblocks and "
"filesystem accounting information: "));
diff --git a/misc/tune2fs.8.in b/misc/tune2fs.8.in
index 260e76f..66d9d52 100644
--- a/misc/tune2fs.8.in
+++ b/misc/tune2fs.8.in
@@ -439,10 +439,19 @@
future.
.B Tune2fs
only supports clearing this filesystem feature.
+.TP
+.B uninit_groups
+Allow the kernel to initialize bitmaps and inode tables and keep a high
+watermark for the unused inodes in a filesystem, to reduce
+.BR e2fsck (8)
+time. This first e2fsck run after enabling this feature will take the
+full time, but subsequent e2fsck runs will take only a fraction of the
+original time, depending on how full the file system is.
.RE
.IP
After setting or clearing
.BR sparse_super ,
+.BR uninit_groups ,
.BR filetype ,
or
.B resize_inode
@@ -457,6 +466,12 @@
feature,
.B e2fsck -D
can be run to convert existing directories to the hashed B-tree format.
+Enabling certain filesystem features may prevent the filesystem from being
+mounted by kernels which do not support those features. In particular the
+.BR uninit_groups
+and
+.BR flex_bg
+features are only supported by the ext4 filesystem.
.TP
.BI \-r " reserved-blocks-count"
Set the number of reserved filesystem blocks.
diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index 4e731f5..85046e2 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -113,9 +113,12 @@
EXT3_FEATURE_COMPAT_HAS_JOURNAL |
EXT2_FEATURE_COMPAT_DIR_INDEX,
/* Incompat */
- EXT2_FEATURE_INCOMPAT_FILETYPE,
+ EXT2_FEATURE_INCOMPAT_FILETYPE |
+ EXT3_FEATURE_INCOMPAT_EXTENTS |
+ EXT4_FEATURE_INCOMPAT_FLEX_BG,
/* R/O compat */
EXT2_FEATURE_RO_COMPAT_LARGE_FILE |
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM |
EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
};
@@ -125,9 +128,11 @@
EXT2_FEATURE_COMPAT_RESIZE_INODE |
EXT2_FEATURE_COMPAT_DIR_INDEX,
/* Incompat */
- EXT2_FEATURE_INCOMPAT_FILETYPE,
+ EXT2_FEATURE_INCOMPAT_FILETYPE |
+ EXT4_FEATURE_INCOMPAT_FLEX_BG,
/* R/O compat */
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE
+ EXT2_FEATURE_RO_COMPAT_LARGE_FILE |
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM
};
/*
@@ -242,6 +247,7 @@
ext2fs_unmark_block_bitmap(fs->block_map,block);
group = ext2fs_group_of_blk(fs, block);
fs->group_desc[group].bg_free_blocks_count++;
+ ext2fs_group_desc_csum_set(fs, group);
fs->super->s_free_blocks_count++;
return 0;
}
@@ -268,7 +274,8 @@
_("while reading bitmaps"));
exit(1);
}
- retval = ext2fs_block_iterate(fs, ino, 0, NULL,
+ retval = ext2fs_block_iterate(fs, ino,
+ BLOCK_FLAG_READ_ONLY, NULL,
release_blocks_proc, NULL);
if (retval) {
com_err(program_name, retval,
@@ -311,7 +318,6 @@
static void update_feature_set(ext2_filsys fs, char *features)
{
struct ext2_super_block *sb= fs->super;
- __u32 old_compat, old_incompat, old_ro_compat;
__u32 old_features[3];
int type_err;
unsigned int mask_err;
@@ -390,6 +396,15 @@
uuid_generate((unsigned char *) sb->s_hash_seed);
}
+ if (FEATURE_OFF(E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
+ if (ext2fs_check_desc(fs)) {
+ fputs(_("Clearing the flex_bg flag would "
+ "cause the the filesystem to be\n"
+ "inconsistent.\n"), stderr);
+ exit(1);
+ }
+ }
+
if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
(sb->s_feature_compat || sb->s_feature_ro_compat ||
sb->s_feature_incompat))
@@ -397,6 +412,8 @@
if (FEATURE_CHANGED(E2P_FEATURE_RO_INCOMPAT,
EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) ||
+ FEATURE_CHANGED(E2P_FEATURE_RO_INCOMPAT,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM) ||
FEATURE_CHANGED(E2P_FEATURE_INCOMPAT,
EXT2_FEATURE_INCOMPAT_FILETYPE) ||
FEATURE_CHANGED(E2P_FEATURE_COMPAT,
diff --git a/misc/util.c b/misc/util.c
index 7522e9b..7c99a2a 100644
--- a/misc/util.c
+++ b/misc/util.c
@@ -71,8 +71,8 @@
fflush(stderr);
fputs(_("Proceed anyway? (y,n) "), stdout);
buf[0] = 0;
- fgets(buf, sizeof(buf), stdin);
- if (strchr(short_yes, buf[0]) == 0)
+ if (!fgets(buf, sizeof(buf), stdin) ||
+ strchr(short_yes, buf[0]) == 0)
exit(1);
}
@@ -249,7 +249,7 @@
* in the filesystem. For very small filesystems, it is not reasonable to
* have a journal that fills more than half of the filesystem.
*/
-int figure_journal_size(int size, ext2_filsys fs)
+unsigned int figure_journal_size(int size, ext2_filsys fs)
{
int j_blocks;
@@ -269,7 +269,7 @@
j_blocks);
exit(1);
}
- if (j_blocks > fs->super->s_free_blocks_count / 2) {
+ if ((unsigned) j_blocks > fs->super->s_free_blocks_count / 2) {
fputs(_("\nJournal size too big for filesystem.\n"),
stderr);
exit(1);
diff --git a/misc/util.h b/misc/util.h
index 3b6a881..0df2aac 100644
--- a/misc/util.h
+++ b/misc/util.h
@@ -22,5 +22,5 @@
extern void check_plausibility(const char *device);
extern void parse_journal_opts(const char *opts);
extern void check_mount(const char *device, int force, const char *type);
-extern int figure_journal_size(int size, ext2_filsys fs);
+extern unsigned int figure_journal_size(int size, ext2_filsys fs);
extern void print_check_message(ext2_filsys fs);
diff --git a/misc/uuidd.c b/misc/uuidd.c
index c964b4e..1af8c86 100644
--- a/misc/uuidd.c
+++ b/misc/uuidd.c
@@ -206,12 +206,12 @@
int debug, int timeout, int quiet)
{
struct sockaddr_un my_addr, from_addr;
- unsigned char reply_buf[1024], *cp;
struct flock fl;
socklen_t fromlen;
int32_t reply_len = 0;
uuid_t uu;
mode_t save_umask;
+ char reply_buf[1024], *cp;
char op, str[37];
int i, s, ns, len, num;
int fd_pidfile, ret;
@@ -329,12 +329,12 @@
switch(op) {
case UUIDD_OP_GETPID:
- sprintf((char *) reply_buf, "%d", getpid());
- reply_len = strlen((char *) reply_buf)+1;
+ sprintf(reply_buf, "%d", getpid());
+ reply_len = strlen(reply_buf)+1;
break;
case UUIDD_OP_GET_MAXOP:
- sprintf((char *) reply_buf, "%d", UUIDD_MAX_OP);
- reply_len = strlen((char *) reply_buf)+1;
+ sprintf(reply_buf, "%d", UUIDD_MAX_OP);
+ reply_len = strlen(reply_buf)+1;
break;
case UUIDD_OP_TIME_UUID:
num = 1;
@@ -375,12 +375,13 @@
num = 1000;
if (num*16 > (int) (sizeof(reply_buf)-sizeof(num)))
num = (sizeof(reply_buf)-sizeof(num)) / 16;
- uuid__generate_random(reply_buf+sizeof(num), &num);
+ uuid__generate_random((unsigned char *) reply_buf +
+ sizeof(num), &num);
if (debug) {
printf(_("Generated %d UUID's:\n"), num);
for (i=0, cp=reply_buf+sizeof(num);
i < num; i++, cp+=16) {
- uuid_unparse(cp, str);
+ uuid_unparse((unsigned char *)cp, str);
printf("\t%s\n", str);
}
}
diff --git a/resize/main.c b/resize/main.c
index f283e41..2e5c89c 100644
--- a/resize/main.c
+++ b/resize/main.c
@@ -36,8 +36,8 @@
static void usage (char *prog)
{
- fprintf (stderr, _("Usage: %s [-d debug_flags] [-f] [-F] [-p] "
- "device [new_size]\n\n"), prog);
+ fprintf (stderr, _("Usage: %s [-d debug_flags] [-f] [-F] [-M] [-P] "
+ "[-p] device [new_size]\n\n"), prog);
exit (1);
}
@@ -152,6 +152,8 @@
int flush = 0;
int force = 0;
int io_flags = 0;
+ int force_min_size = 0;
+ int print_min_size = 0;
int fd, ret;
blk_t new_size = 0;
blk_t max_size = 0;
@@ -183,7 +185,7 @@
if (argc && *argv)
program_name = *argv;
- while ((c = getopt (argc, argv, "d:fFhpS:")) != EOF) {
+ while ((c = getopt (argc, argv, "d:fFhMPpS:")) != EOF) {
switch (c) {
case 'h':
usage(program_name);
@@ -194,6 +196,12 @@
case 'F':
flush = 1;
break;
+ case 'M':
+ force_min_size = 1;
+ break;
+ case 'P':
+ print_min_size = 1;
+ break;
case 'd':
flags |= atoi(optarg);
break;
@@ -298,6 +306,13 @@
printf (_("Couldn't find valid filesystem superblock.\n"));
exit (1);
}
+
+ if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
+ com_err(program_name, EXT2_ET_RO_UNSUPP_FEATURE,
+ ":- uninit_groups");
+ exit(1);
+ }
+
/*
* Check for compatibility with the feature sets. We need to
* be more stringent than ext2fs_open().
@@ -308,6 +323,12 @@
exit(1);
}
+ if (print_min_size) {
+ printf("Estimated minimum size of the filesystem: %lu\n",
+ calculate_minimum_resize_size(fs));
+ exit(0);
+ }
+
/* Determine the system page size if possible */
#ifdef HAVE_SYSCONF
#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE))
@@ -332,14 +353,11 @@
_("while trying to determine filesystem size"));
exit(1);
}
- if (new_size_str) {
+ if (force_min_size)
+ new_size = calculate_minimum_resize_size(fs);
+ else if (new_size_str) {
new_size = parse_num_blocks(new_size_str,
fs->super->s_log_block_size);
- if (!new_size) {
- com_err(program_name, 0, _("bad filesystem size - %s"),
- new_size_str);
- exit(1);
- }
} else {
new_size = max_size;
/* Round down to an even multiple of a pagesize */
diff --git a/resize/resize2fs.8.in b/resize/resize2fs.8.in
index d43adad..719ef99 100644
--- a/resize/resize2fs.8.in
+++ b/resize/resize2fs.8.in
@@ -8,6 +8,9 @@
.SH SYNOPSIS
.B resize2fs
[
+.B \-fFpPM
+]
+[
.B \-d
.I debug-flags
]
@@ -15,15 +18,6 @@
.B \-S
.I RAID-stride
]
-[
-.B \-f
-]
-[
-.B \-F
-]
-[
-.B \-p
-]
.I device
[
.I size
@@ -99,19 +93,6 @@
\ 8\ \-\ Debug inode relocations
.br
\ 16\ \-\ Debug moving the inode table
-.TP
-.B \-S \fIRAID-stride
-The
-.B resize2fs
-program will heuristically determine the RAID stride that was specified
-when the filesystem was created. This option allows the user to
-explicitly specify a RAID stride setting to be used by resize2fs instead.
-.TP
-.B \-p
-Prints out a percentage completion bars for each
-.B resize2fs
-operation, so that the user can keep track of what
-the program is doing.
.TP
.B \-f
Forces resize2fs to proceed with the filesystem resize operation, overriding
@@ -122,6 +103,28 @@
really useful for doing
.B resize2fs
time trials.
+.TP
+.B \-M
+Shrink the filesystem to the minimum size.
+.TP
+.B \-p
+Prints out a percentage completion bars for each
+.B resize2fs
+operation, so that the user can keep track of what
+the program is doing.
+.TP
+.B \-P
+Print the minimum size of the filesystem and exit.
+.TP
+.B \-S \fIRAID-stride
+The
+.B resize2fs
+program will heuristically determine the RAID stride that was specified
+when the filesystem was created. This option allows the user to
+explicitly specify a RAID stride setting to be used by resize2fs instead.
+.SH KNOWN BUGS
+The minimum size of the filesystem as estimated by resize2fs may be
+incorrect, especially for filesystems with 1k and 2k blocksizes.
.SH AUTHOR
.B resize2fs
was written by Theodore Ts'o <tytso@mit.edu>.
diff --git a/resize/resize2fs.c b/resize/resize2fs.c
index 6dec3eb..1062ffa 100644
--- a/resize/resize2fs.c
+++ b/resize/resize2fs.c
@@ -63,7 +63,9 @@
((blk) < (FS_INODE_TB((fs), (i)) + \
(fs)->inode_blocks_per_group)))
-
+#define META_OVERHEAD(fs) (2 + (fs)->inode_blocks_per_group)
+#define SUPER_OVERHEAD(fs) (1 + (fs)->desc_blocks +\
+ (fs)->super->s_reserved_gdt_blocks)
/*
* This is the top-level routine which does the dirty deed....
@@ -339,7 +341,8 @@
numblocks = fs->super->s_blocks_per_group;
i = old_fs->group_desc_count - 1;
fs->group_desc[i].bg_free_blocks_count += (numblocks-old_numblocks);
-
+ ext2fs_group_desc_csum_set(fs, i);
+
/*
* If the number of block groups is staying the same, we're
* done and can exit now. (If the number block groups is
@@ -383,8 +386,7 @@
ext2fs_mark_block_bitmap(fs->block_map, group_block);
adjblocks++;
}
- meta_bg_size = (fs->blocksize /
- sizeof (struct ext2_group_desc));
+ meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
meta_bg = i / meta_bg_size;
if (!(fs->super->s_feature_incompat &
EXT2_FEATURE_INCOMPAT_META_BG) ||
@@ -415,6 +417,7 @@
fs->group_desc[i].bg_free_inodes_count =
fs->super->s_inodes_per_group;
fs->group_desc[i].bg_used_dirs_count = 0;
+ ext2fs_group_desc_csum_set(fs, i);
retval = ext2fs_allocate_group_table(fs, i, 0);
if (retval) goto errout;
@@ -550,7 +553,7 @@
unsigned long meta_bg_size;
unsigned int old_desc_blocks;
- meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc));
+ meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
old_desc_blocks = fs->super->s_first_meta_bg;
else
@@ -717,7 +720,7 @@
* If we're increasing the number of descriptor blocks, life
* gets interesting....
*/
- meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc));
+ meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
for (i = 0; i < max_groups; i++) {
has_super = ext2fs_bg_has_super(fs, i);
if (has_super)
@@ -1232,9 +1235,11 @@
if (retval) goto errout;
group = (new_inode-1) / EXT2_INODES_PER_GROUP(rfs->new_fs->super);
- if (LINUX_S_ISDIR(inode->i_mode))
+ if (LINUX_S_ISDIR(inode->i_mode)) {
rfs->new_fs->group_desc[group].bg_used_dirs_count++;
-
+ ext2fs_group_desc_csum_set(rfs->new_fs, group);
+ }
+
#ifdef RESIZE2FS_DEBUG
if (rfs->flags & RESIZE_DEBUG_INODEMAP)
printf("Inode moved %u->%u\n", ino, new_inode);
@@ -1489,6 +1494,7 @@
ext2fs_unmark_block_bitmap(fs->block_map, blk);
rfs->old_fs->group_desc[i].bg_inode_table = new_blk;
+ ext2fs_group_desc_csum_set(rfs->old_fs, i);
ext2fs_mark_super_dirty(rfs->old_fs);
ext2fs_flush(rfs->old_fs);
@@ -1586,8 +1592,10 @@
count++;
if ((count == fs->super->s_blocks_per_group) ||
(blk == fs->super->s_blocks_count-1)) {
- fs->group_desc[group++].bg_free_blocks_count =
+ fs->group_desc[group].bg_free_blocks_count =
group_free;
+ ext2fs_group_desc_csum_set(fs, group);
+ group++;
count = 0;
group_free = 0;
}
@@ -1611,8 +1619,10 @@
count++;
if ((count == fs->super->s_inodes_per_group) ||
(ino == fs->super->s_inodes_count)) {
- fs->group_desc[group++].bg_free_inodes_count =
+ fs->group_desc[group].bg_free_inodes_count =
group_free;
+ ext2fs_group_desc_csum_set(fs, group);
+ group++;
count = 0;
group_free = 0;
}
@@ -1621,3 +1631,139 @@
ext2fs_mark_super_dirty(fs);
return 0;
}
+
+/*
+ * calcluate the minimum number of blocks the given fs can be resized to
+ */
+blk_t calculate_minimum_resize_size(ext2_filsys fs)
+{
+ blk_t inode_count, blks_needed, groups, blk, data_blocks;
+ blk_t grp, data_needed, last_start;
+ int overhead = 0, old_group = -1, num_of_superblocks = 0;
+
+ /*
+ * first figure out how many group descriptors we need to
+ * handle the number of inodes we have
+ */
+ inode_count = fs->super->s_inodes_count -
+ fs->super->s_free_inodes_count;
+ blks_needed = ext2fs_div_ceil(inode_count,
+ fs->super->s_inodes_per_group) *
+ EXT2_BLOCKS_PER_GROUP(fs->super);
+ groups = ext2fs_div_ceil(blks_needed,
+ EXT2_BLOCKS_PER_GROUP(fs->super));
+
+ /*
+ * we need to figure out how many backup superblocks we have so we can
+ * account for that in the metadata
+ */
+ for (grp = 0; grp < fs->group_desc_count; grp++) {
+ if (ext2fs_bg_has_super(fs, grp))
+ num_of_superblocks++;
+ }
+
+ /* calculate how many blocks are needed for data */
+ data_needed = fs->super->s_blocks_count -
+ fs->super->s_free_blocks_count;
+ data_needed -= SUPER_OVERHEAD(fs) * num_of_superblocks;
+ data_needed -= META_OVERHEAD(fs) * fs->group_desc_count;
+
+ /*
+ * figure out how many data blocks we have given the number of groups
+ * we need for our inodes
+ */
+ data_blocks = groups * EXT2_BLOCKS_PER_GROUP(fs->super);
+ last_start = 0;
+ for (grp = 0; grp < groups; grp++) {
+ overhead = META_OVERHEAD(fs);
+
+ if (ext2fs_bg_has_super(fs, grp))
+ overhead += SUPER_OVERHEAD(fs);
+
+ /*
+ * we want to keep track of how much data we can store in
+ * the groups leading up to the last group so we can determine
+ * how big the last group needs to be
+ */
+ if (grp != (groups - 1))
+ last_start += EXT2_BLOCKS_PER_GROUP(fs->super) -
+ overhead;
+
+ data_blocks -= overhead;
+ }
+
+ /*
+ * if we need more group descriptors in order to accomodate our data
+ * then we need to add them here
+ */
+ while (data_needed > data_blocks) {
+ blk_t remainder = data_needed - data_blocks;
+ blk_t extra_grps;
+
+ /* figure out how many more groups we need for the data */
+ extra_grps = ext2fs_div_ceil(remainder,
+ EXT2_BLOCKS_PER_GROUP(fs->super));
+
+ data_blocks += extra_grps * EXT2_BLOCKS_PER_GROUP(fs->super);
+
+ /* ok we have to account for the last group */
+ overhead = META_OVERHEAD(fs);
+ if (ext2fs_bg_has_super(fs, groups-1))
+ overhead += SUPER_OVERHEAD(fs);
+ last_start += EXT2_BLOCKS_PER_GROUP(fs->super) - overhead;
+
+ for (grp = groups; grp < groups+extra_grps; grp++) {
+ overhead = META_OVERHEAD(fs);
+ if (ext2fs_bg_has_super(fs, grp))
+ overhead += SUPER_OVERHEAD(fs);
+
+ /*
+ * again, we need to see how much data we cram into
+ * all of the groups leading up to the last group
+ */
+ if (grp != (groups + extra_grps - 1))
+ last_start += EXT2_BLOCKS_PER_GROUP(fs->super)
+ - overhead;
+
+ data_blocks -= overhead;
+ }
+
+ groups += extra_grps;
+ }
+
+ /* now for the fun voodoo */
+ overhead = META_OVERHEAD(fs);
+
+ /*
+ * if this is the case then the last group is going to have data in it
+ * so we need to adjust the size of the last group accordingly
+ */
+ if (last_start < data_needed) {
+ blk_t remainder = data_needed - last_start;
+
+ /*
+ * 50 is a magic number that mkfs/resize uses to see if its
+ * even worth making/resizing the fs. basically you need to
+ * have at least 50 blocks in addition to the blocks needed
+ * for the metadata in the last group
+ */
+ if (remainder > 50)
+ overhead += remainder;
+ else
+ overhead += 50;
+ } else
+ overhead += 50;
+
+ if (ext2fs_bg_has_super(fs, groups-1))
+ overhead += SUPER_OVERHEAD(fs);
+
+ /*
+ * since our last group doesn't have to be BLOCKS_PER_GROUP large, we
+ * only do groups-1, and then add the number of blocks needed to
+ * handle the group descriptor metadata+data that we need
+ */
+ blks_needed = (groups-1) * EXT2_BLOCKS_PER_GROUP(fs->super);
+ blks_needed += overhead;
+
+ return blks_needed;
+}
diff --git a/resize/resize2fs.h b/resize/resize2fs.h
index f87d04e..49b77d8 100644
--- a/resize/resize2fs.h
+++ b/resize/resize2fs.h
@@ -129,6 +129,7 @@
extern errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
blk_t new_size);
+extern blk_t calculate_minimum_resize_size(ext2_filsys fs);
/* extent.c */
diff --git a/tests/f_bad_disconnected_inode/expect.1 b/tests/f_bad_disconnected_inode/expect.1
index b4851f0..11862f6 100644
--- a/tests/f_bad_disconnected_inode/expect.1
+++ b/tests/f_bad_disconnected_inode/expect.1
@@ -1,4 +1,13 @@
Pass 1: Checking inodes, blocks, and sizes
+Inode 1 has EXTENTS_FL flag set on filesystem without extents support.
+Clear? yes
+
+Inode 15 has EXTENTS_FL flag set on filesystem without extents support.
+Clear? yes
+
+Inode 16 has EXTENTS_FL flag set on filesystem without extents support.
+Clear? yes
+
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
/lost+found not found. Create? yes
@@ -18,26 +27,6 @@
Inode 14 (...) has invalid mode (0154247).
Clear? yes
-i_file_acl for inode 15 (...) is 1143674715, should be zero.
-Clear? yes
-
-Inode 15 (...) has invalid mode (074044).
-Clear? yes
-
-i_file_acl for inode 16 (...) is 2007517039, should be zero.
-Clear? yes
-
-i_faddr for inode 16 (...) is 1003914917, should be zero.
-Clear? yes
-
-i_blocks_hi for inode 16 (...) is 62762, should be zero.
-Clear? yes
-
-Unattached inode 16
-Connect to /lost+found? yes
-
-Inode 16 ref count is 5925, should be 1. Fix? yes
-
Pass 5: Checking group summary information
Block bitmap differences: -(9--19)
Fix? yes
@@ -48,19 +37,16 @@
Free blocks count wrong (79, counted=91).
Fix? yes
-Inode bitmap differences: +16
-Fix? yes
-
-Free inodes count wrong for group #0 (7, counted=4).
+Free inodes count wrong for group #0 (6, counted=5).
Fix? yes
Directories count wrong for group #0 (3, counted=2).
Fix? yes
-Free inodes count wrong (7, counted=4).
+Free inodes count wrong (6, counted=5).
Fix? yes
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
-test_filesys: 12/16 files (0.0% non-contiguous), 9/100 blocks
+test_filesys: 11/16 files (0.0% non-contiguous), 9/100 blocks
Exit status is 1
diff --git a/tests/f_bad_disconnected_inode/expect.2 b/tests/f_bad_disconnected_inode/expect.2
index 1739210..8dfeb70 100644
--- a/tests/f_bad_disconnected_inode/expect.2
+++ b/tests/f_bad_disconnected_inode/expect.2
@@ -3,5 +3,5 @@
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-test_filesys: 12/16 files (0.0% non-contiguous), 9/100 blocks
+test_filesys: 11/16 files (0.0% non-contiguous), 9/100 blocks
Exit status is 0
diff --git a/tests/f_dupfsblks/expect.1 b/tests/f_dupfsblks/expect.1
index 661e164..32ce89b 100644
--- a/tests/f_dupfsblks/expect.1
+++ b/tests/f_dupfsblks/expect.1
@@ -44,7 +44,8 @@
Directory inode 12, block 3, offset 0: directory corrupted
Salvage? yes
-Entry '' in ??? (12) has deleted/unused inode 32. Clear? yes
+Entry '' in ??? (12) has a zero-length name.
+Clear? yes
Directory inode 12, block 4, offset 100: directory corrupted
Salvage? yes
diff --git a/tests/f_ea_checks/expect.1 b/tests/f_ea_checks/expect.1
new file mode 100644
index 0000000..eb215a2
--- /dev/null
+++ b/tests/f_ea_checks/expect.1
@@ -0,0 +1,57 @@
+Pass 1: Checking inodes, blocks, and sizes
+Inode 13 has a bad extended attribute block 26. Clear? yes
+
+Inode 13, i_blocks is 4, should be 2. Fix? yes
+
+Extended attribute in inode 14 has a hash (1649340189) which is invalid
+Clear? yes
+
+Inode 14, i_blocks is 2, should be 0. Fix? yes
+
+Inode 17 has a bad extended attribute block 28. Clear? yes
+
+Inode 17, i_blocks is 4, should be 2. Fix? yes
+
+Inode 16 has a bad extended attribute block 29. Clear? yes
+
+Inode 16, i_blocks is 2, should be 0. Fix? yes
+
+Inode 19 has a bad extended attribute block 33. Clear? yes
+
+Inode 19, i_blocks is 2, should be 0. Fix? yes
+
+Inode 12 has a bad extended attribute block 55. Clear? yes
+
+Inode 12, i_blocks is 2, should be 0. Fix? yes
+
+Inode 15, i_blocks is 2, should be 0. Fix? yes
+
+Pass 2: Checking directory structure
+Extended attribute block for inode 15 (/far) is invalid (999).
+Clear? yes
+
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Block bitmap differences: -(26--29) -33 -55
+Fix? yes
+
+Free blocks count wrong for group #0 (481, counted=484).
+Fix? yes
+
+Free blocks count wrong (481, counted=484).
+Fix? yes
+
+Inode bitmap differences: -18
+Fix? yes
+
+Free inodes count wrong for group #0 (47, counted=46).
+Fix? yes
+
+Free inodes count wrong (47, counted=46).
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 18/64 files (0.0% non-contiguous), 28/512 blocks
+Exit status is 1
diff --git a/tests/f_ea_checks/expect.2 b/tests/f_ea_checks/expect.2
new file mode 100644
index 0000000..2a11cd2
--- /dev/null
+++ b/tests/f_ea_checks/expect.2
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 18/64 files (0.0% non-contiguous), 28/512 blocks
+Exit status is 0
diff --git a/tests/f_ea_checks/image.gz b/tests/f_ea_checks/image.gz
new file mode 100644
index 0000000..253da06
--- /dev/null
+++ b/tests/f_ea_checks/image.gz
Binary files differ
diff --git a/tests/f_ea_checks/name b/tests/f_ea_checks/name
new file mode 100644
index 0000000..160fdea
--- /dev/null
+++ b/tests/f_ea_checks/name
@@ -0,0 +1 @@
+extended attribute block checks
diff --git a/tests/f_extents/expect.1 b/tests/f_extents/expect.1
new file mode 100644
index 0000000..2abe32e
--- /dev/null
+++ b/tests/f_extents/expect.1
@@ -0,0 +1,52 @@
+Pass 1: Checking inodes, blocks, and sizes
+Inode 12 is in extent format, but superblock is missing EXTENTS feature
+Fix? yes
+
+Inode 12 has an invalid extent
+ (logical block 0, invalid physical block 21994527527949, len 17)
+Clear? yes
+
+Inode 12, i_blocks is 34, should be 0. Fix? yes
+
+Inode 13 missing EXTENT_FL, but is in extents format
+Fix? yes
+
+Inode 17 has an invalid extent
+ (logical block 0, invalid physical block 22011707397135, len 15)
+Clear? yes
+
+Inode 17, i_blocks is 32, should be 0. Fix? yes
+
+Error while reading over extent tree in inode 18: Corrupt extent header
+Clear inode? yes
+
+Inode 18, i_blocks is 2, should be 0. Fix? yes
+
+Pass 2: Checking directory structure
+Entry 'fbad-flag' in / (2) has deleted/unused inode 18. Clear? yes
+
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Block bitmap differences: -1081 +4611 -(5121--5142)
+Fix? yes
+
+Free blocks count wrong for group #0 (7081, counted=7098).
+Fix? yes
+
+Free blocks count wrong (7081, counted=7098).
+Fix? yes
+
+Inode bitmap differences: -18
+Fix? yes
+
+Free inodes count wrong for group #0 (237, counted=238).
+Fix? yes
+
+Free inodes count wrong (237, counted=238).
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 18/256 files (0.0% non-contiguous), 1094/8192 blocks
+Exit status is 1
diff --git a/tests/f_extents/expect.2 b/tests/f_extents/expect.2
new file mode 100644
index 0000000..6162cdf
--- /dev/null
+++ b/tests/f_extents/expect.2
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 18/256 files (0.0% non-contiguous), 1094/8192 blocks
+Exit status is 0
diff --git a/tests/f_extents/name b/tests/f_extents/name
new file mode 100644
index 0000000..edede57
--- /dev/null
+++ b/tests/f_extents/name
@@ -0,0 +1 @@
+basic extents support
diff --git a/tests/f_extents/script b/tests/f_extents/script
deleted file mode 100644
index c046675..0000000
--- a/tests/f_extents/script
+++ /dev/null
@@ -1,2 +0,0 @@
-rm -f $test_name.ok $test_name.failed
-echo "skipped"
diff --git a/tests/f_fast_symlink_extents/expect.1 b/tests/f_fast_symlink_extents/expect.1
new file mode 100644
index 0000000..dc16c97
--- /dev/null
+++ b/tests/f_fast_symlink_extents/expect.1
@@ -0,0 +1,11 @@
+Pass 1: Checking inodes, blocks, and sizes
+Fast symlink 13 has EXTENT_FL set. Clear? yes
+
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 13/16 files (0.0% non-contiguous), 21/100 blocks
+Exit status is 1
diff --git a/tests/f_fast_symlink_extents/expect.2 b/tests/f_fast_symlink_extents/expect.2
new file mode 100644
index 0000000..416f49c
--- /dev/null
+++ b/tests/f_fast_symlink_extents/expect.2
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 13/16 files (0.0% non-contiguous), 21/100 blocks
+Exit status is 0
diff --git a/tests/f_fast_symlink_extents/image.gz b/tests/f_fast_symlink_extents/image.gz
new file mode 100644
index 0000000..37eb0af
--- /dev/null
+++ b/tests/f_fast_symlink_extents/image.gz
Binary files differ
diff --git a/tests/f_fast_symlink_extents/name b/tests/f_fast_symlink_extents/name
new file mode 100644
index 0000000..333cb52
--- /dev/null
+++ b/tests/f_fast_symlink_extents/name
@@ -0,0 +1 @@
+fast symlink with extents flag set
diff --git a/tests/f_swapfs/debugfs.cmd b/tests/f_swapfs/debugfs.cmd
deleted file mode 100644
index df583b2..0000000
--- a/tests/f_swapfs/debugfs.cmd
+++ /dev/null
@@ -1,5 +0,0 @@
-ls
-stat sym
-stat double-indirect-test
-cat fluff
-quit
diff --git a/tests/f_swapfs/expect b/tests/f_swapfs/expect
deleted file mode 100644
index ecbb990..0000000
--- a/tests/f_swapfs/expect
+++ /dev/null
@@ -1,133 +0,0 @@
-Swapfs test
-e2fsck -yf -N test_filesys
-Pass 1: Checking inodes, blocks, and sizes
-Pass 2: Checking directory structure
-Pass 3: Checking directory connectivity
-Pass 4: Checking reference counts
-Pass 5: Checking group summary information
-test_filesys: 25/256 files (0.0% non-contiguous), 418/1024 blocks
-Exit status is 0
-e2fsck -Sy -N test_filesys
-Pass 0: Doing byte-swap of filesystem
-Pass 1: Checking inodes, blocks, and sizes
-Pass 2: Checking directory structure
-Pass 3: Checking directory connectivity
-Pass 4: Checking reference counts
-Pass 5: Checking group summary information
-test_filesys: 25/256 files (0.0% non-contiguous), 418/1024 blocks
-Exit status is 0
-Running debugfs....
-debugfs: ls
- 2 (12) . 2 (12) .. 11 (20) lost+found 12 (16) fluff
- 13 (28) indirect-fluff-test 14 (28) double-indirect-test
- 15 (20) sym 16 (24) long-sym-test 17 (864) dir-test
-debugfs: stat sym
-Inode: 15 Type: symlink Mode: 0777 Flags: 0x0 Generation: 1
-User: 0 Group: 0 Size: 5
-File ACL: 0 Directory ACL: 0
-Links: 1 Blockcount: 0
-Fragment: Address: 0 Number: 0 Size: 0
-ctime: 0x322737e2 -- Fri Aug 30 18:50:10 1996
-atime: 0x322737e2 -- Fri Aug 30 18:50:10 1996
-mtime: 0x322737e2 -- Fri Aug 30 18:50:10 1996
-Fast_link_dest: fluff
-debugfs: stat double-indirect-test
-Inode: 14 Type: regular Mode: 0644 Flags: 0x0 Generation: 1
-User: 0 Group: 0 Size: 348960
-File ACL: 0 Directory ACL: 0
-Links: 1 Blockcount: 688
-Fragment: Address: 0 Number: 0 Size: 0
-ctime: 0x322488cf -- Wed Aug 28 17:58:39 1996
-atime: 0x322488cf -- Wed Aug 28 17:58:39 1996
-mtime: 0x322488cf -- Wed Aug 28 17:58:39 1996
-BLOCKS:
-(0-11):70-81, (IND):82, (12-267):83-338, (DIND):339, (IND):340, (268-340):341-413
-TOTAL: 344
-
-debugfs: cat fluff
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-
-debugfs: quit
-Exit status is 0
-e2fsck -yf -N test_filesys
-Pass 1: Checking inodes, blocks, and sizes
-Pass 2: Checking directory structure
-Pass 3: Checking directory connectivity
-Pass 4: Checking reference counts
-Pass 5: Checking group summary information
-test_filesys: 25/256 files (0.0% non-contiguous), 418/1024 blocks
-Exit status is 0
-e2fsck -sy -N test_filesys
-Pass 0: Doing byte-swap of filesystem
-Pass 1: Checking inodes, blocks, and sizes
-Pass 2: Checking directory structure
-Pass 3: Checking directory connectivity
-Pass 4: Checking reference counts
-Pass 5: Checking group summary information
-test_filesys: 25/256 files (0.0% non-contiguous), 418/1024 blocks
-Exit status is 0
-Running debugfs....
-debugfs: ls
- 2 (12) . 2 (12) .. 11 (20) lost+found 12 (16) fluff
- 13 (28) indirect-fluff-test 14 (28) double-indirect-test
- 15 (20) sym 16 (24) long-sym-test 17 (864) dir-test
-debugfs: stat sym
-Inode: 15 Type: symlink Mode: 0777 Flags: 0x0 Generation: 1
-User: 0 Group: 0 Size: 5
-File ACL: 0 Directory ACL: 0
-Links: 1 Blockcount: 0
-Fragment: Address: 0 Number: 0 Size: 0
-ctime: 0x322737e2 -- Fri Aug 30 18:50:10 1996
-atime: 0x322737e2 -- Fri Aug 30 18:50:10 1996
-mtime: 0x322737e2 -- Fri Aug 30 18:50:10 1996
-Fast_link_dest: fluff
-debugfs: stat double-indirect-test
-Inode: 14 Type: regular Mode: 0644 Flags: 0x0 Generation: 1
-User: 0 Group: 0 Size: 348960
-File ACL: 0 Directory ACL: 0
-Links: 1 Blockcount: 688
-Fragment: Address: 0 Number: 0 Size: 0
-ctime: 0x322488cf -- Wed Aug 28 17:58:39 1996
-atime: 0x322488cf -- Wed Aug 28 17:58:39 1996
-mtime: 0x322488cf -- Wed Aug 28 17:58:39 1996
-BLOCKS:
-(0-11):70-81, (IND):82, (12-267):83-338, (DIND):339, (IND):340, (268-340):341-413
-TOTAL: 344
-
-debugfs: cat fluff
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-yabba dabba doo. cocka doodle doo. yabba dabba doo. cocka doodle doo. yipyip
-
-debugfs: quit
-Exit status is 0
-e2fsck -yf -N test_filesys
-Pass 1: Checking inodes, blocks, and sizes
-Pass 2: Checking directory structure
-Pass 3: Checking directory connectivity
-Pass 4: Checking reference counts
-Pass 5: Checking group summary information
-test_filesys: 25/256 files (0.0% non-contiguous), 418/1024 blocks
-Exit status is 0
diff --git a/tests/f_swapfs/image b/tests/f_swapfs/image
deleted file mode 100644
index e7b24b9..0000000
--- a/tests/f_swapfs/image
+++ /dev/null
Binary files differ
diff --git a/tests/f_swapfs/image.gz b/tests/f_swapfs/image.gz
deleted file mode 100644
index 852231b..0000000
--- a/tests/f_swapfs/image.gz
+++ /dev/null
Binary files differ
diff --git a/tests/f_swapfs/name b/tests/f_swapfs/name
deleted file mode 100644
index b4520ba..0000000
--- a/tests/f_swapfs/name
+++ /dev/null
@@ -1 +0,0 @@
-checking the e2fsck swapfs functionality
diff --git a/tests/f_swapfs/script b/tests/f_swapfs/script
deleted file mode 100644
index 75f9fb4..0000000
--- a/tests/f_swapfs/script
+++ /dev/null
@@ -1,79 +0,0 @@
-if $FSCK -SV > /dev/null 2>&1 ; then
- IMAGE=$test_dir/image.gz
- VERIFY_FSCK_OPT=-yf
- SWAP_FSCK_OPT=-Sy
- NATIVE_FSCK_OPT=-sy
- OUT=$test_name.log
- EXP=$test_dir/expect
-
- gunzip < $IMAGE > $TMPFILE
-
- echo "Swapfs test" > $OUT
-
- echo e2fsck $VERIFY_FSCK_OPT -N test_filesys > $OUT.new
- $FSCK $VERIFY_FSCK_OPT -N test_filesys $TMPFILE >> $OUT.new 2>&1
- status=$?
- echo Exit status is $status >> $OUT.new
- sed -e '2d' $OUT.new >> $OUT
-
- echo e2fsck $SWAP_FSCK_OPT -N test_filesys > $OUT.new
- $FSCK $SWAP_FSCK_OPT -N test_filesys $TMPFILE >> $OUT.new 2>&1
- status=$?
- echo Exit status is $status >> $OUT.new
- sed -e '2d' $OUT.new >> $OUT
-
- echo Running debugfs.... >> $OUT
- $DEBUGFS -f $test_dir/debugfs.cmd $TMPFILE > $OUT.new 2>&1
- status=$?
- echo Exit status is $status >> $OUT.new
- sed -e '1d' $OUT.new >> $OUT
-
- echo e2fsck $VERIFY_FSCK_OPT -N test_filesys > $OUT.new
- $FSCK $VERIFY_FSCK_OPT -N test_filesys $TMPFILE >> $OUT.new 2>&1
- status=$?
- echo Exit status is $status >> $OUT.new
- sed -e '2d' $OUT.new >> $OUT
-
- echo e2fsck $NATIVE_FSCK_OPT -N test_filesys > $OUT.new
- $FSCK $NATIVE_FSCK_OPT -N test_filesys $TMPFILE >> $OUT.new 2>&1
- status=$?
- echo Exit status is $status >> $OUT.new
- sed -e '2d' $OUT.new >> $OUT
-
- echo Running debugfs.... >> $OUT
- $DEBUGFS -f $test_dir/debugfs.cmd $TMPFILE > $OUT.new 2>&1
- status=$?
- echo Exit status is $status >> $OUT.new
- sed -e '1d' $OUT.new >> $OUT
-
- echo e2fsck $VERIFY_FSCK_OPT -N test_filesys > $OUT.new
- $FSCK $VERIFY_FSCK_OPT -N test_filesys $TMPFILE >> $OUT.new 2>&1
- status=$?
- echo Exit status is $status >> $OUT.new
- sed -e '2d' $OUT.new >> $OUT
- rm -f $OUT.new
-
- rm $TMPFILE
-
- #
- # Do the verification
- #
-
- rm -f $test_name.ok $test_name.failed
- cmp -s $OUT $EXP
- status=$?
-
- if [ "$status" = 0 ] ; then
- echo "ok"
- touch $test_name.ok
- else
- echo "failed"
- diff $DIFF_OPTS $EXP $OUT > $test_name.failed
- fi
-
- unset IMAGE VERIFY_FSCK_OPT SWAP_FSCK_OPT NATIVE_FSCK_OPT OUT EXP
-
-else
- rm -f $test_name.ok $test_name.failed
- echo "skipped"
-fi
diff --git a/tests/f_uninit_last_uninit/expect.1 b/tests/f_uninit_last_uninit/expect.1
new file mode 100644
index 0000000..85f05ee
--- /dev/null
+++ b/tests/f_uninit_last_uninit/expect.1
@@ -0,0 +1,9 @@
+Last group block bitmap uninitialized. Fix? yes
+
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 11/32 files (9.1% non-contiguous), 105/10000 blocks
+Exit status is 0
diff --git a/tests/f_uninit_last_uninit/expect.2 b/tests/f_uninit_last_uninit/expect.2
new file mode 100644
index 0000000..435a8a7
--- /dev/null
+++ b/tests/f_uninit_last_uninit/expect.2
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 11/32 files (9.1% non-contiguous), 105/10000 blocks
+Exit status is 0
diff --git a/tests/f_uninit_last_uninit/name b/tests/f_uninit_last_uninit/name
new file mode 100644
index 0000000..4f93e23
--- /dev/null
+++ b/tests/f_uninit_last_uninit/name
@@ -0,0 +1,2 @@
+last group has BLOCK_UNINIT set
+
diff --git a/tests/f_uninit_last_uninit/script b/tests/f_uninit_last_uninit/script
new file mode 100644
index 0000000..477357a
--- /dev/null
+++ b/tests/f_uninit_last_uninit/script
@@ -0,0 +1,20 @@
+SKIP_GUNZIP="true"
+
+touch $TMPFILE
+$MKE2FS -N 32 -F -o Linux -O uninit_groups -b 1024 $TMPFILE 10000 > /dev/null 2>&1
+$DEBUGFS -w $TMPFILE << EOF > /dev/null 2>&1
+set_current_time 200704102100
+set_super_value lastcheck 0
+set_super_value hash_seed null
+set_super_value mkfs_time 0
+set_bg 1 flags 0x7
+set_bg 1 checksum calc
+q
+EOF
+
+E2FSCK_TIME=200704102100
+export E2FSCK_TIME
+
+. $cmd_dir/run_e2fsck
+
+unset E2FSCK_TIME
diff --git a/tests/f_unsorted_EAs/expect.1 b/tests/f_unsorted_EAs/expect.1
new file mode 100644
index 0000000..7d588d7
--- /dev/null
+++ b/tests/f_unsorted_EAs/expect.1
@@ -0,0 +1,11 @@
+Adding dirhash hint to filesystem.
+
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 12/2048 files (0.0% non-contiguous), 1294/2048 blocks
+Exit status is 1
diff --git a/tests/f_unsorted_EAs/expect.2 b/tests/f_unsorted_EAs/expect.2
new file mode 100644
index 0000000..414cc29
--- /dev/null
+++ b/tests/f_unsorted_EAs/expect.2
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 12/2048 files (0.0% non-contiguous), 1294/2048 blocks
+Exit status is 0
diff --git a/tests/f_unsorted_EAs/image.gz b/tests/f_unsorted_EAs/image.gz
new file mode 100644
index 0000000..42ab502
--- /dev/null
+++ b/tests/f_unsorted_EAs/image.gz
Binary files differ
diff --git a/tests/f_unsorted_EAs/name b/tests/f_unsorted_EAs/name
new file mode 100644
index 0000000..da9c9c3
--- /dev/null
+++ b/tests/f_unsorted_EAs/name
@@ -0,0 +1 @@
+unsorted EAs in inode should not be deleted
diff --git a/tests/filter_dumpe2fs b/tests/filter_dumpe2fs
index 51211f3..daa2c97 100644
--- a/tests/filter_dumpe2fs
+++ b/tests/filter_dumpe2fs
@@ -10,3 +10,4 @@
/^Maximum mount count:/d
/Reserved blocks uid:/s/ (user .*)//
/Reserved blocks gid:/s/ (group .*)//
+/^ Checksum /d
diff --git a/tests/m_large_file/expect.1 b/tests/m_large_file/expect.1
index 2323eac..6a6c856 100644
--- a/tests/m_large_file/expect.1
+++ b/tests/m_large_file/expect.1
@@ -1,4 +1,3 @@
-Warning: 256-byte inodes not usable on older systems
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
diff --git a/tests/m_lazy/expect.1 b/tests/m_lazy/expect.1
new file mode 100644
index 0000000..88bd5c6
--- /dev/null
+++ b/tests/m_lazy/expect.1
@@ -0,0 +1,158 @@
+Filesystem label=
+OS type: Linux
+Block size=1024 (log=0)
+Fragment size=1024 (log=0)
+32768 inodes, 131072 blocks
+6553 blocks (5.00%) reserved for the super user
+First data block=1
+16 block groups
+8192 blocks per group, 8192 fragments per group
+2048 inodes per group
+Superblock backups stored on blocks:
+ 8193, 24577, 40961, 57345, 73729
+
+Writing inode tables: done
+Writing superblocks and filesystem accounting information: done
+
+Filesystem features: ext_attr dir_index lazy_bg filetype sparse_super
+
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 28683/32768 files (0.0% non-contiguous), 115220/131072 blocks
+Exit status is 0
+
+Filesystem volume name: <none>
+Last mounted on: <not available>
+Filesystem magic number: 0xEF53
+Filesystem revision #: 1 (dynamic)
+Filesystem features: ext_attr dir_index lazy_bg filetype sparse_super
+Default mount options: (none)
+Filesystem state: clean
+Errors behavior: Continue
+Filesystem OS type: Linux
+Inode count: 32768
+Block count: 131072
+Reserved block count: 6553
+Free blocks: 15852
+Free inodes: 4085
+First block: 1
+Block size: 1024
+Fragment size: 1024
+Blocks per group: 8192
+Fragments per group: 8192
+Inodes per group: 2048
+Inode blocks per group: 256
+Mount count: 0
+Check interval: 15552000 (6 months)
+Reserved blocks uid: 0
+Reserved blocks gid: 0
+First inode: 11
+Inode size: 128
+Default directory hash: tea
+
+
+Group 0: (Blocks 1-8192) [ITABLE_ZEROED]
+ Primary superblock at 1, Group descriptors at 2-2
+ Block bitmap at 3 (+2), Inode bitmap at 4 (+3)
+ Inode table at 5-260 (+4)
+ 7919 free blocks, 2037 free inodes, 2 directories
+ Free blocks: 274-8192
+ Free inodes: 12-2048
+Group 1: (Blocks 8193-16384) [INODE_UNINIT, BLOCK_UNINIT]
+ Backup superblock at 8193, Group descriptors at 8194-8194
+ Block bitmap at 8195 (+2), Inode bitmap at 8196 (+3)
+ Inode table at 8197-8452 (+4)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 2: (Blocks 16385-24576) [INODE_UNINIT, BLOCK_UNINIT]
+ Block bitmap at 16385 (+0), Inode bitmap at 16386 (+1)
+ Inode table at 16387-16642 (+2)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 3: (Blocks 24577-32768) [INODE_UNINIT, BLOCK_UNINIT]
+ Backup superblock at 24577, Group descriptors at 24578-24578
+ Block bitmap at 24579 (+2), Inode bitmap at 24580 (+3)
+ Inode table at 24581-24836 (+4)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 4: (Blocks 32769-40960) [INODE_UNINIT, BLOCK_UNINIT]
+ Block bitmap at 32769 (+0), Inode bitmap at 32770 (+1)
+ Inode table at 32771-33026 (+2)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 5: (Blocks 40961-49152) [INODE_UNINIT, BLOCK_UNINIT]
+ Backup superblock at 40961, Group descriptors at 40962-40962
+ Block bitmap at 40963 (+2), Inode bitmap at 40964 (+3)
+ Inode table at 40965-41220 (+4)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 6: (Blocks 49153-57344) [INODE_UNINIT, BLOCK_UNINIT]
+ Block bitmap at 49153 (+0), Inode bitmap at 49154 (+1)
+ Inode table at 49155-49410 (+2)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 7: (Blocks 57345-65536) [INODE_UNINIT, BLOCK_UNINIT]
+ Backup superblock at 57345, Group descriptors at 57346-57346
+ Block bitmap at 57347 (+2), Inode bitmap at 57348 (+3)
+ Inode table at 57349-57604 (+4)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 8: (Blocks 65537-73728) [INODE_UNINIT, BLOCK_UNINIT]
+ Block bitmap at 65537 (+0), Inode bitmap at 65538 (+1)
+ Inode table at 65539-65794 (+2)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 9: (Blocks 73729-81920) [INODE_UNINIT, BLOCK_UNINIT]
+ Backup superblock at 73729, Group descriptors at 73730-73730
+ Block bitmap at 73731 (+2), Inode bitmap at 73732 (+3)
+ Inode table at 73733-73988 (+4)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 10: (Blocks 81921-90112) [INODE_UNINIT, BLOCK_UNINIT]
+ Block bitmap at 81921 (+0), Inode bitmap at 81922 (+1)
+ Inode table at 81923-82178 (+2)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 11: (Blocks 90113-98304) [INODE_UNINIT, BLOCK_UNINIT]
+ Block bitmap at 90113 (+0), Inode bitmap at 90114 (+1)
+ Inode table at 90115-90370 (+2)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 12: (Blocks 98305-106496) [INODE_UNINIT, BLOCK_UNINIT]
+ Block bitmap at 98305 (+0), Inode bitmap at 98306 (+1)
+ Inode table at 98307-98562 (+2)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 13: (Blocks 106497-114688) [INODE_UNINIT, BLOCK_UNINIT]
+ Block bitmap at 106497 (+0), Inode bitmap at 106498 (+1)
+ Inode table at 106499-106754 (+2)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 14: (Blocks 114689-122880) [INODE_UNINIT, BLOCK_UNINIT]
+ Block bitmap at 114689 (+0), Inode bitmap at 114690 (+1)
+ Inode table at 114691-114946 (+2)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 15: (Blocks 122881-131071) [ITABLE_ZEROED]
+ Block bitmap at 122881 (+0), Inode bitmap at 122882 (+1)
+ Inode table at 122883-123138 (+2)
+ 7933 free blocks, 2048 free inodes, 0 directories
+ Free blocks: 123139-131071
+ Free inodes: 30721-32768
diff --git a/tests/m_lazy/script b/tests/m_lazy/script
new file mode 100644
index 0000000..aaac8f0
--- /dev/null
+++ b/tests/m_lazy/script
@@ -0,0 +1,4 @@
+DESCRIPTION="lazy group feature"
+FS_SIZE=131072
+MKE2FS_OPTS="-O ^resize_inode,lazy_bg"
+. $cmd_dir/run_mke2fs
diff --git a/tests/m_lazy_resize/expect.1 b/tests/m_lazy_resize/expect.1
new file mode 100644
index 0000000..b1f6b5e
--- /dev/null
+++ b/tests/m_lazy_resize/expect.1
@@ -0,0 +1,166 @@
+Filesystem label=
+OS type: Linux
+Block size=1024 (log=0)
+Fragment size=1024 (log=0)
+32768 inodes, 131072 blocks
+6553 blocks (5.00%) reserved for the super user
+First data block=1
+Maximum filesystem blocks=67371008
+16 block groups
+8192 blocks per group, 8192 fragments per group
+2048 inodes per group
+Superblock backups stored on blocks:
+ 8193, 24577, 40961, 57345, 73729
+
+Writing inode tables: done
+Writing superblocks and filesystem accounting information: done
+
+Filesystem features: ext_attr resize_inode dir_index lazy_bg filetype sparse_super
+
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 28683/32768 files (0.0% non-contiguous), 77097/131072 blocks
+Exit status is 0
+
+Filesystem volume name: <none>
+Last mounted on: <not available>
+Filesystem magic number: 0xEF53
+Filesystem revision #: 1 (dynamic)
+Filesystem features: ext_attr resize_inode dir_index lazy_bg filetype sparse_super
+Default mount options: (none)
+Filesystem state: clean
+Errors behavior: Continue
+Filesystem OS type: Linux
+Inode count: 32768
+Block count: 131072
+Reserved block count: 6553
+Free blocks: 53975
+Free inodes: 4085
+First block: 1
+Block size: 1024
+Fragment size: 1024
+Reserved GDT blocks: 256
+Blocks per group: 8192
+Fragments per group: 8192
+Inodes per group: 2048
+Inode blocks per group: 256
+Mount count: 0
+Check interval: 15552000 (6 months)
+Reserved blocks uid: 0
+Reserved blocks gid: 0
+First inode: 11
+Inode size: 128
+Default directory hash: tea
+
+
+Group 0: (Blocks 1-8192) [ITABLE_ZEROED]
+ Primary superblock at 1, Group descriptors at 2-2
+ Reserved GDT blocks at 3-258
+ Block bitmap at 259 (+258), Inode bitmap at 260 (+259)
+ Inode table at 261-516 (+260)
+ 7662 free blocks, 2037 free inodes, 2 directories
+ Free blocks: 531-8192
+ Free inodes: 12-2048
+Group 1: (Blocks 8193-16384) [INODE_UNINIT]
+ Backup superblock at 8193, Group descriptors at 8194-8194
+ Reserved GDT blocks at 8195-8450
+ Block bitmap at 8451 (+258), Inode bitmap at 8452 (+259)
+ Inode table at 8453-8708 (+260)
+ 7676 free blocks, 0 free inodes, 0 directories
+ Free blocks: 8709-16384
+ Free inodes:
+Group 2: (Blocks 16385-24576) [INODE_UNINIT, BLOCK_UNINIT]
+ Block bitmap at 16385 (+0), Inode bitmap at 16386 (+1)
+ Inode table at 16387-16642 (+2)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 3: (Blocks 24577-32768) [INODE_UNINIT]
+ Backup superblock at 24577, Group descriptors at 24578-24578
+ Reserved GDT blocks at 24579-24834
+ Block bitmap at 24835 (+258), Inode bitmap at 24836 (+259)
+ Inode table at 24837-25092 (+260)
+ 7676 free blocks, 0 free inodes, 0 directories
+ Free blocks: 25093-32768
+ Free inodes:
+Group 4: (Blocks 32769-40960) [INODE_UNINIT, BLOCK_UNINIT]
+ Block bitmap at 32769 (+0), Inode bitmap at 32770 (+1)
+ Inode table at 32771-33026 (+2)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 5: (Blocks 40961-49152) [INODE_UNINIT]
+ Backup superblock at 40961, Group descriptors at 40962-40962
+ Reserved GDT blocks at 40963-41218
+ Block bitmap at 41219 (+258), Inode bitmap at 41220 (+259)
+ Inode table at 41221-41476 (+260)
+ 7676 free blocks, 0 free inodes, 0 directories
+ Free blocks: 41477-49152
+ Free inodes:
+Group 6: (Blocks 49153-57344) [INODE_UNINIT, BLOCK_UNINIT]
+ Block bitmap at 49153 (+0), Inode bitmap at 49154 (+1)
+ Inode table at 49155-49410 (+2)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 7: (Blocks 57345-65536) [INODE_UNINIT]
+ Backup superblock at 57345, Group descriptors at 57346-57346
+ Reserved GDT blocks at 57347-57602
+ Block bitmap at 57603 (+258), Inode bitmap at 57604 (+259)
+ Inode table at 57605-57860 (+260)
+ 7676 free blocks, 0 free inodes, 0 directories
+ Free blocks: 57861-65536
+ Free inodes:
+Group 8: (Blocks 65537-73728) [INODE_UNINIT, BLOCK_UNINIT]
+ Block bitmap at 65537 (+0), Inode bitmap at 65538 (+1)
+ Inode table at 65539-65794 (+2)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 9: (Blocks 73729-81920) [INODE_UNINIT]
+ Backup superblock at 73729, Group descriptors at 73730-73730
+ Reserved GDT blocks at 73731-73986
+ Block bitmap at 73987 (+258), Inode bitmap at 73988 (+259)
+ Inode table at 73989-74244 (+260)
+ 7676 free blocks, 0 free inodes, 0 directories
+ Free blocks: 74245-81920
+ Free inodes:
+Group 10: (Blocks 81921-90112) [INODE_UNINIT, BLOCK_UNINIT]
+ Block bitmap at 81921 (+0), Inode bitmap at 81922 (+1)
+ Inode table at 81923-82178 (+2)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 11: (Blocks 90113-98304) [INODE_UNINIT, BLOCK_UNINIT]
+ Block bitmap at 90113 (+0), Inode bitmap at 90114 (+1)
+ Inode table at 90115-90370 (+2)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 12: (Blocks 98305-106496) [INODE_UNINIT, BLOCK_UNINIT]
+ Block bitmap at 98305 (+0), Inode bitmap at 98306 (+1)
+ Inode table at 98307-98562 (+2)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 13: (Blocks 106497-114688) [INODE_UNINIT, BLOCK_UNINIT]
+ Block bitmap at 106497 (+0), Inode bitmap at 106498 (+1)
+ Inode table at 106499-106754 (+2)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 14: (Blocks 114689-122880) [INODE_UNINIT, BLOCK_UNINIT]
+ Block bitmap at 114689 (+0), Inode bitmap at 114690 (+1)
+ Inode table at 114691-114946 (+2)
+ 0 free blocks, 0 free inodes, 0 directories
+ Free blocks:
+ Free inodes:
+Group 15: (Blocks 122881-131071) [ITABLE_ZEROED]
+ Block bitmap at 122881 (+0), Inode bitmap at 122882 (+1)
+ Inode table at 122883-123138 (+2)
+ 7933 free blocks, 2048 free inodes, 0 directories
+ Free blocks: 123139-131071
+ Free inodes: 30721-32768
diff --git a/tests/m_lazy_resize/script b/tests/m_lazy_resize/script
new file mode 100644
index 0000000..2ba081f
--- /dev/null
+++ b/tests/m_lazy_resize/script
@@ -0,0 +1,4 @@
+DESCRIPTION="lazy group feature with resize_inode"
+FS_SIZE=131072
+MKE2FS_OPTS="-O resize_inode,lazy_bg"
+. $cmd_dir/run_mke2fs
diff --git a/tests/m_raid_opt/expect.1 b/tests/m_raid_opt/expect.1
index 9bd7894..25b283a 100644
--- a/tests/m_raid_opt/expect.1
+++ b/tests/m_raid_opt/expect.1
@@ -46,57 +46,68 @@
Directory inode 11, block 1, offset 0: directory corrupted
Salvage? yes
-Entry '' in ??? (11) has deleted/unused inode 1063. Clear? yes
+Entry '' in ??? (11) has a zero-length name.
+Clear? yes
Directory inode 11, block 2, offset 0: directory corrupted
Salvage? yes
-Entry '' in ??? (11) has deleted/unused inode 1064. Clear? yes
+Entry '' in ??? (11) has a zero-length name.
+Clear? yes
Directory inode 11, block 3, offset 0: directory corrupted
Salvage? yes
-Entry '' in ??? (11) has deleted/unused inode 1065. Clear? yes
+Entry '' in ??? (11) has a zero-length name.
+Clear? yes
Directory inode 11, block 4, offset 0: directory corrupted
Salvage? yes
-Entry '' in ??? (11) has deleted/unused inode 1066. Clear? yes
+Entry '' in ??? (11) has a zero-length name.
+Clear? yes
Directory inode 11, block 5, offset 0: directory corrupted
Salvage? yes
-Entry '' in ??? (11) has deleted/unused inode 1067. Clear? yes
+Entry '' in ??? (11) has a zero-length name.
+Clear? yes
Directory inode 11, block 6, offset 0: directory corrupted
Salvage? yes
-Entry '' in ??? (11) has deleted/unused inode 1068. Clear? yes
+Entry '' in ??? (11) has a zero-length name.
+Clear? yes
Directory inode 11, block 7, offset 0: directory corrupted
Salvage? yes
-Entry '' in ??? (11) has deleted/unused inode 1069. Clear? yes
+Entry '' in ??? (11) has a zero-length name.
+Clear? yes
Directory inode 11, block 8, offset 0: directory corrupted
Salvage? yes
-Entry '' in ??? (11) has deleted/unused inode 1070. Clear? yes
+Entry '' in ??? (11) has a zero-length name.
+Clear? yes
Directory inode 11, block 9, offset 0: directory corrupted
Salvage? yes
-Entry '' in ??? (11) has deleted/unused inode 1071. Clear? yes
+Entry '' in ??? (11) has a zero-length name.
+Clear? yes
Directory inode 11, block 10, offset 0: directory corrupted
Salvage? yes
-Entry '' in ??? (11) has deleted/unused inode 1072. Clear? yes
+Entry '' in ??? (11) has a zero-length name.
+Clear? yes
Directory inode 11, block 11, offset 0: directory corrupted
Salvage? yes
-Entry '' in ??? (11) has deleted/unused inode 1073. Clear? yes
+Entry '' in ??? (11) has a zero-length name.
+Clear? yes
Pass 3: Checking directory connectivity
'..' in / (2) is <The NULL inode> (0), should be / (2).
diff --git a/tests/m_uninit/expect.1 b/tests/m_uninit/expect.1
new file mode 100644
index 0000000..93cea7b
--- /dev/null
+++ b/tests/m_uninit/expect.1
@@ -0,0 +1,166 @@
+Filesystem label=
+OS type: Linux
+Block size=1024 (log=0)
+Fragment size=1024 (log=0)
+32768 inodes, 131072 blocks
+6553 blocks (5.00%) reserved for the super user
+First data block=1
+Maximum filesystem blocks=67371008
+16 block groups
+8192 blocks per group, 8192 fragments per group
+2048 inodes per group
+Superblock backups stored on blocks:
+ 8193, 24577, 40961, 57345, 73729
+
+Writing inode tables: done
+Writing superblocks and filesystem accounting information: done
+
+Filesystem features: ext_attr resize_inode dir_index filetype sparse_super uninit_groups
+
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 11/32768 files (9.1% non-contiguous), 5691/131072 blocks
+Exit status is 0
+
+Filesystem volume name: <none>
+Last mounted on: <not available>
+Filesystem magic number: 0xEF53
+Filesystem revision #: 1 (dynamic)
+Filesystem features: ext_attr resize_inode dir_index filetype sparse_super uninit_groups
+Default mount options: (none)
+Filesystem state: clean
+Errors behavior: Continue
+Filesystem OS type: Linux
+Inode count: 32768
+Block count: 131072
+Reserved block count: 6553
+Free blocks: 125381
+Free inodes: 32757
+First block: 1
+Block size: 1024
+Fragment size: 1024
+Reserved GDT blocks: 256
+Blocks per group: 8192
+Fragments per group: 8192
+Inodes per group: 2048
+Inode blocks per group: 256
+Mount count: 0
+Check interval: 15552000 (6 months)
+Reserved blocks uid: 0
+Reserved blocks gid: 0
+First inode: 11
+Inode size: 128
+Default directory hash: tea
+
+
+Group 0: (Blocks 1-8192) [ITABLE_ZEROED]
+ Primary superblock at 1, Group descriptors at 2-2
+ Reserved GDT blocks at 3-258
+ Block bitmap at 259 (+258), Inode bitmap at 260 (+259)
+ Inode table at 261-516 (+260)
+ 7662 free blocks, 2037 free inodes, 2 directories, 2037 unused inodes
+ Free blocks: 531-8192
+ Free inodes: 12-2048
+Group 1: (Blocks 8193-16384) [INODE_UNINIT, ITABLE_ZEROED]
+ Backup superblock at 8193, Group descriptors at 8194-8194
+ Reserved GDT blocks at 8195-8450
+ Block bitmap at 8451 (+258), Inode bitmap at 8452 (+259)
+ Inode table at 8453-8708 (+260)
+ 7676 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
+ Free blocks: 8709-16384
+ Free inodes:
+Group 2: (Blocks 16385-24576) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
+ Block bitmap at 16385 (+0), Inode bitmap at 16386 (+1)
+ Inode table at 16387-16642 (+2)
+ 7934 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
+ Free blocks:
+ Free inodes:
+Group 3: (Blocks 24577-32768) [INODE_UNINIT, ITABLE_ZEROED]
+ Backup superblock at 24577, Group descriptors at 24578-24578
+ Reserved GDT blocks at 24579-24834
+ Block bitmap at 24835 (+258), Inode bitmap at 24836 (+259)
+ Inode table at 24837-25092 (+260)
+ 7676 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
+ Free blocks: 25093-32768
+ Free inodes:
+Group 4: (Blocks 32769-40960) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
+ Block bitmap at 32769 (+0), Inode bitmap at 32770 (+1)
+ Inode table at 32771-33026 (+2)
+ 7934 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
+ Free blocks:
+ Free inodes:
+Group 5: (Blocks 40961-49152) [INODE_UNINIT, ITABLE_ZEROED]
+ Backup superblock at 40961, Group descriptors at 40962-40962
+ Reserved GDT blocks at 40963-41218
+ Block bitmap at 41219 (+258), Inode bitmap at 41220 (+259)
+ Inode table at 41221-41476 (+260)
+ 7676 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
+ Free blocks: 41477-49152
+ Free inodes:
+Group 6: (Blocks 49153-57344) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
+ Block bitmap at 49153 (+0), Inode bitmap at 49154 (+1)
+ Inode table at 49155-49410 (+2)
+ 7934 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
+ Free blocks:
+ Free inodes:
+Group 7: (Blocks 57345-65536) [INODE_UNINIT, ITABLE_ZEROED]
+ Backup superblock at 57345, Group descriptors at 57346-57346
+ Reserved GDT blocks at 57347-57602
+ Block bitmap at 57603 (+258), Inode bitmap at 57604 (+259)
+ Inode table at 57605-57860 (+260)
+ 7676 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
+ Free blocks: 57861-65536
+ Free inodes:
+Group 8: (Blocks 65537-73728) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
+ Block bitmap at 65537 (+0), Inode bitmap at 65538 (+1)
+ Inode table at 65539-65794 (+2)
+ 7934 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
+ Free blocks:
+ Free inodes:
+Group 9: (Blocks 73729-81920) [INODE_UNINIT, ITABLE_ZEROED]
+ Backup superblock at 73729, Group descriptors at 73730-73730
+ Reserved GDT blocks at 73731-73986
+ Block bitmap at 73987 (+258), Inode bitmap at 73988 (+259)
+ Inode table at 73989-74244 (+260)
+ 7676 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
+ Free blocks: 74245-81920
+ Free inodes:
+Group 10: (Blocks 81921-90112) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
+ Block bitmap at 81921 (+0), Inode bitmap at 81922 (+1)
+ Inode table at 81923-82178 (+2)
+ 7934 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
+ Free blocks:
+ Free inodes:
+Group 11: (Blocks 90113-98304) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
+ Block bitmap at 90113 (+0), Inode bitmap at 90114 (+1)
+ Inode table at 90115-90370 (+2)
+ 7934 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
+ Free blocks:
+ Free inodes:
+Group 12: (Blocks 98305-106496) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
+ Block bitmap at 98305 (+0), Inode bitmap at 98306 (+1)
+ Inode table at 98307-98562 (+2)
+ 7934 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
+ Free blocks:
+ Free inodes:
+Group 13: (Blocks 106497-114688) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
+ Block bitmap at 106497 (+0), Inode bitmap at 106498 (+1)
+ Inode table at 106499-106754 (+2)
+ 7934 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
+ Free blocks:
+ Free inodes:
+Group 14: (Blocks 114689-122880) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
+ Block bitmap at 114689 (+0), Inode bitmap at 114690 (+1)
+ Inode table at 114691-114946 (+2)
+ 7934 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
+ Free blocks:
+ Free inodes:
+Group 15: (Blocks 122881-131071) [INODE_UNINIT, ITABLE_ZEROED]
+ Block bitmap at 122881 (+0), Inode bitmap at 122882 (+1)
+ Inode table at 122883-123138 (+2)
+ 7933 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
+ Free blocks: 123139-131071
+ Free inodes:
diff --git a/tests/m_uninit/script b/tests/m_uninit/script
new file mode 100644
index 0000000..0de2699
--- /dev/null
+++ b/tests/m_uninit/script
@@ -0,0 +1,4 @@
+DESCRIPTION="uninitialized group feature"
+FS_SIZE=131072
+MKE2FS_OPTS="-O uninit_groups"
+. $cmd_dir/run_mke2fs