aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2014-02-04 23:15:43 -0500
committerTheodore Ts'o <tytso@mit.edu>2014-02-04 23:15:43 -0500
commit8e47ef51975f5d46245f04fddcdd8cf7d02ba060 (patch)
tree5c3ed7868e71eff01b035cb77f146e50de3ef49d
parent80a41277c4bc6676b1e3bc8d8228f4acfb343ca1 (diff)
downloade2fsprogs-debian-1.42.9.tar.gz
debian: update debian/patches for 1.42.9-3 releasedebian-1.42.9
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r--debian/patches/series1
-rw-r--r--debian/patches/update-to-git-f3ff319f796066
2 files changed, 6067 insertions, 0 deletions
diff --git a/debian/patches/series b/debian/patches/series
index 45b462d78..431f3b483 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,3 +1,4 @@
fix-spec-file-version
fix-printf-format-type-match
fix-debugfs-block-parse-error-reporting
+update-to-git-f3ff319f79
diff --git a/debian/patches/update-to-git-f3ff319f79 b/debian/patches/update-to-git-f3ff319f79
new file mode 100644
index 000000000..d85f53c25
--- /dev/null
+++ b/debian/patches/update-to-git-f3ff319f79
@@ -0,0 +1,6066 @@
+Description: update to e2fsprogs git commit f3ff319f79
+ .
+ e2fsprogs (1.42.9-3) unstable; urgency=medium
+ .
+ * Add the ability for mke2fs to create hugefiles
+ * Add support for the sparse_super2 compat feature
+ * Mke2fs can now force all of the metadata blocks to be at the
+ beginning of the file system
+ * Fix loopback mount detection (Closes: #497984)
+ * Add support to mke2fs to create a file system at an offset
+ (Closes: #417385)
+ * Mention badblocks in the package description (Closes: #718725)
+ * Update/fix various man pages (Closes: #719184, #719189)
+ * Improve e2fsck's "superblock corrupt" message (Closes: #719185)
+ * Miscellaneous Coverity clean ups
+Author: Theodore Y. Ts'o <tytso@mit.edu>
+Origin: upstream<vendor|upstream|other>, <url of original patch>
+Bug-Debian: http://bugs.debian.org/417385
+Bug-Debian: http://bugs.debian.org/497984
+Bug-Debian: http://bugs.debian.org/718725
+Bug-Debian: http://bugs.debian.org/719184
+Bug-Debian: http://bugs.debian.org/719185
+Bug-Debian: http://bugs.debian.org/719189
+
+---
+The information above should follow the Patch Tagging Guidelines, please
+checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
+are templates for supplementary fields that you might want to add:
+
+Origin: <vendor|upstream|other>, <url of original patch>
+Bug: <url in upstream bugtracker>
+Bug-Debian: http://bugs.debian.org/<bugnumber>
+Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
+Forwarded: <no|not-needed|url proving that it has been forwarded>
+Reviewed-By: <name and email of someone who approved the patch>
+Last-Update: <YYYY-MM-DD>
+
+--- e2fsprogs-1.42.9.orig/MCONFIG.in
++++ e2fsprogs-1.42.9/MCONFIG.in
+@@ -110,6 +110,7 @@ LIBUUID = @LIBUUID@ @SOCKET_LIB@
+ LIBQUOTA = @STATIC_LIBQUOTA@
+ LIBBLKID = @LIBBLKID@ @PRIVATE_LIBS_CMT@ $(LIBUUID)
+ LIBINTL = @LIBINTL@
++SYSLIBS = @LIBS@
+ DEPLIBSS = $(LIB)/libss@LIB_EXT@
+ DEPLIBCOM_ERR = $(LIB)/libcom_err@LIB_EXT@
+ DEPLIBUUID = @DEPLIBUUID@
+--- e2fsprogs-1.42.9.orig/configure
++++ e2fsprogs-1.42.9/configure
+@@ -2753,6 +2753,21 @@ $as_echo "Release date is ${E2FSPROGS_MO
+
+
+
++WITH_DIET_LIBC=
++
++# Check whether --with-diet-libc was given.
++if test "${with_diet_libc+set}" = set; then :
++ withval=$with_diet_libc; CC="diet cc -nostdinc"
++WITH_DIET_LIBC=yes
++if test -z "$LIBS"
++then
++ LIBS="-lcompat"
++else
++ LIBS="$LIBS -lcompat"
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: CC=$CC" >&5
++$as_echo "CC=$CC" >&6; }
++fi
+ # Make sure we can run config.sub.
+ $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+@@ -3659,15 +3674,6 @@ $as_echo "#define HAVE_DLOPEN 1" >>confd
+ fi
+
+
+-WITH_DIET_LIBC=
+-
+-# Check whether --with-diet-libc was given.
+-if test "${with_diet_libc+set}" = set; then :
+- withval=$with_diet_libc; CC="diet cc -nostdinc"
+-WITH_DIET_LIBC=yes
+-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: CC=$CC" >&5
+-$as_echo "CC=$CC" >&6; }
+-fi
+
+ # Check whether --with-cc was given.
+ if test "${with_cc+set}" = set; then :
+@@ -5440,9 +5446,16 @@ $as_echo "Enabling e4defrag support" >&6
+ fi
+
+ else
+- { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling e4defrag support by default" >&5
++ if test -z "$WITH_DIET_LIBC"
++then
++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling e4defrag support by default" >&5
+ $as_echo "Enabling e4defrag support by default" >&6; }
+-DEFRAG_CMT=
++ DEFRAG_CMT=
++else
++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling e4defrag support by default" >&5
++$as_echo "Disabling e4defrag support by default" >&6; }
++ DEFRAG_CMT="#"
++fi
+
+ fi
+
+@@ -10448,6 +10461,16 @@ $as_echo "#define HAVE_RECLEN_DIRENT 1"
+
+ fi
+
++ac_fn_c_check_member "$LINENO" "struct stat" "st_atim" "ac_cv_member_struct_stat_st_atim" "$ac_includes_default"
++if test "x$ac_cv_member_struct_stat_st_atim" = xyes; then :
++
++cat >>confdefs.h <<_ACEOF
++#define HAVE_STRUCT_STAT_ST_ATIM 1
++_ACEOF
++
++
++fi
++
+ ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "#include <sys/types.h>
+ "
+ if test "x$ac_cv_type_ssize_t" = xyes; then :
+@@ -11041,7 +11064,7 @@ if test "$ac_res" != no; then :
+ fi
+
+ fi
+-for ac_func in __secure_getenv backtrace blkid_probe_get_topology chflags fallocate fallocate64 fchown fdatasync fstat64 ftruncate64 getdtablesize getmntinfo getpwuid_r getrlimit getrusage jrand48 llseek lseek64 mallinfo mbstowcs memalign mmap msync nanosleep open64 pathconf posix_fadvise posix_memalign prctl secure_getenv setmntent setresgid setresuid srandom strcasecmp strdup strnlen strptime strtoull sync_file_range sysconf usleep utime valloc
++for ac_func in __secure_getenv backtrace blkid_probe_get_topology chflags fadvise64 fallocate fallocate64 fchown fdatasync fstat64 ftruncate64 futimes getcwd getdtablesize getmntinfo getpwuid_r getrlimit getrusage jrand48 llseek lseek64 mallinfo mbstowcs memalign mempcpy mmap msync nanosleep open64 pathconf posix_fadvise posix_fadvise64 posix_memalign prctl secure_getenv setmntent setresgid setresuid srandom stpcpy strcasecmp strdup strnlen strptime strtoull sync_file_range sysconf usleep utime valloc
+ do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+@@ -11425,9 +11448,12 @@ fi
+ if test "$USE_INCLUDED_LIBINTL" = "yes" ; then
+ INCLUDES=$INCLUDES' -I$(top_builddir)/intl -I$(top_srcdir)/intl'
+ fi
++if test -n "$WITH_DIET_LIBC" ; then
++ INCLUDES="$INCLUDES -D_REENTRANT"
++fi
+
+ if test $cross_compiling = no; then
+- BUILD_CFLAGS="$CFLAGS $CPPFLAGS"
++ BUILD_CFLAGS="$CFLAGS $CPPFLAGS $INCLUDES -DHAVE_CONFIG_H"
+ BUILD_LDFLAGS="$LDFLAGS"
+ else
+ BUILD_CFLAGS=
+--- e2fsprogs-1.42.9.orig/configure.in
++++ e2fsprogs-1.42.9/configure.in
+@@ -2,7 +2,7 @@ AC_INIT(version.h)
+ AC_PREREQ(2.54)
+ AC_CONFIG_AUX_DIR(config)
+ AC_CONFIG_HEADERS([lib/config.h])
+-AH_BOTTOM([#include "dirpaths.h"])
++AH_BOTTOM([#include <dirpaths.h>])
+ MCONFIG=./MCONFIG
+ AC_SUBST_FILE(MCONFIG)
+ BINARY_TYPE=bin
+@@ -63,15 +63,6 @@ AC_SUBST(E2FSPROGS_MONTH)
+ AC_SUBST(E2FSPROGS_DAY)
+ AC_SUBST(E2FSPROGS_VERSION)
+ AC_SUBST(E2FSPROGS_PKGVER)
+-AC_CANONICAL_HOST
+-dnl
+-dnl Check to see if libdl exists for the sake of dlopen
+-dnl
+-DLOPEN_LIB=''
+-AC_CHECK_LIB(dl, dlopen,
+-[DLOPEN_LIB=-ldl
+-AC_DEFINE(HAVE_DLOPEN, 1, [Define to 1 if dlopen/libdl exists])])
+-AC_SUBST(DLOPEN_LIB)
+ dnl
+ dnl Use diet libc
+ dnl
+@@ -80,8 +71,24 @@ AC_ARG_WITH([diet-libc],
+ [ --with-diet-libc use diet libc],
+ CC="diet cc -nostdinc"
+ WITH_DIET_LIBC=yes
++if test -z "$LIBS"
++then
++ LIBS="-lcompat"
++else
++ LIBS="$LIBS -lcompat"
++fi
+ AC_MSG_RESULT(CC=$CC))dnl
+ dnl
++AC_CANONICAL_HOST
++dnl
++dnl Check to see if libdl exists for the sake of dlopen
++dnl
++DLOPEN_LIB=''
++AC_CHECK_LIB(dl, dlopen,
++[DLOPEN_LIB=-ldl
++AC_DEFINE(HAVE_DLOPEN, 1, [Define to 1 if dlopen/libdl exists])])
++AC_SUBST(DLOPEN_LIB)
++dnl
+ AC_ARG_WITH([cc],
+ AC_HELP_STRING([--with-cc],[no longer supported, use CC= instead]),
+ AC_MSG_ERROR([--with-cc no longer supported; use CC= instead]))
+@@ -687,8 +694,14 @@ else
+ AC_MSG_RESULT([Enabling e4defrag support])
+ fi
+ ,
+-AC_MSG_RESULT([Enabling e4defrag support by default])
+-DEFRAG_CMT=
++if test -z "$WITH_DIET_LIBC"
++then
++ AC_MSG_RESULT([Enabling e4defrag support by default])
++ DEFRAG_CMT=
++else
++ AC_MSG_RESULT([Disabling e4defrag support by default])
++ DEFRAG_CMT="#"
++fi
+ )
+ AC_SUBST(DEFRAG_CMT)
+ dnl
+@@ -909,6 +922,7 @@ dnl is not decleared.
+ AC_CHECK_MEMBER(struct dirent.d_reclen,[AC_DEFINE(HAVE_RECLEN_DIRENT, 1,
+ [Define to 1 if dirent has d_reclen])],,
+ [#include <dirent.h>])
++AC_CHECK_MEMBERS([struct stat.st_atim])
+ dnl Check to see if ssize_t was declared
+ AC_CHECK_TYPE(ssize_t,[AC_DEFINE(HAVE_TYPE_SSIZE_T, 1,
+ [Define to 1 if ssize_t declared])],,
+@@ -1025,12 +1039,15 @@ AC_CHECK_FUNCS(m4_flatten([
+ backtrace
+ blkid_probe_get_topology
+ chflags
++ fadvise64
+ fallocate
+ fallocate64
+ fchown
+ fdatasync
+ fstat64
+ ftruncate64
++ futimes
++ getcwd
+ getdtablesize
+ getmntinfo
+ getpwuid_r
+@@ -1042,12 +1059,14 @@ AC_CHECK_FUNCS(m4_flatten([
+ mallinfo
+ mbstowcs
+ memalign
++ mempcpy
+ mmap
+ msync
+ nanosleep
+ open64
+ pathconf
+ posix_fadvise
++ posix_fadvise64
+ posix_memalign
+ prctl
+ secure_getenv
+@@ -1055,6 +1074,7 @@ AC_CHECK_FUNCS(m4_flatten([
+ setresgid
+ setresuid
+ srandom
++ stpcpy
+ strcasecmp
+ strdup
+ strnlen
+@@ -1275,12 +1295,15 @@ fi
+ if test "$USE_INCLUDED_LIBINTL" = "yes" ; then
+ INCLUDES=$INCLUDES' -I$(top_builddir)/intl -I$(top_srcdir)/intl'
+ fi
++if test -n "$WITH_DIET_LIBC" ; then
++ INCLUDES="$INCLUDES -D_REENTRANT"
++fi
+ AC_SUBST(INCLUDES)
+ dnl
+ dnl Build CFLAGS
+ dnl
+ if test $cross_compiling = no; then
+- BUILD_CFLAGS="$CFLAGS $CPPFLAGS"
++ BUILD_CFLAGS="$CFLAGS $CPPFLAGS $INCLUDES -DHAVE_CONFIG_H"
+ BUILD_LDFLAGS="$LDFLAGS"
+ else
+ BUILD_CFLAGS=
+--- e2fsprogs-1.42.9.orig/debugfs/Makefile.in
++++ e2fsprogs-1.42.9/debugfs/Makefile.in
+@@ -31,12 +31,12 @@ SRCS= debug_cmds.c $(srcdir)/debugfs.c $
+ $(srcdir)/filefrag.c $(srcdir)/extent_inode.c $(srcdir)/zap.c
+
+ LIBS= $(LIBEXT2FS) $(LIBE2P) $(LIBSS) $(LIBCOM_ERR) $(LIBBLKID) \
+- $(LIBUUID)
++ $(LIBUUID) $(SYSLIBS)
+ DEPLIBS= $(LIBEXT2FS) $(LIBE2P) $(DEPLIBSS) $(DEPLIBCOM_ERR) \
+ $(DEPLIBBLKID) $(DEPLIBUUID)
+
+ STATIC_LIBS= $(STATIC_LIBEXT2FS) $(STATIC_LIBSS) $(STATIC_LIBCOM_ERR) \
+- $(STATIC_LIBBLKID) $(STATIC_LIBUUID) $(STATIC_LIBE2P)
++ $(STATIC_LIBBLKID) $(STATIC_LIBUUID) $(STATIC_LIBE2P) $(SYSLIBS)
+ STATIC_DEPLIBS= $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBSS) \
+ $(DEPSTATIC_LIBCOM_ERR) $(DEPSTATIC_LIBUUID) \
+ $(DEPSTATIC_LIBE2P)
+--- e2fsprogs-1.42.9.orig/debugfs/debugfs.c
++++ e2fsprogs-1.42.9/debugfs/debugfs.c
+@@ -289,8 +289,6 @@ void do_init_filesys(int argc, char **ar
+ if (err)
+ return;
+ ext2fs_blocks_count_set(&param, blocks);
+- if (err)
+- return;
+ retval = ext2fs_initialize(argv[1], 0, &param,
+ unix_io_manager, &current_fs);
+ if (retval) {
+--- e2fsprogs-1.42.9.orig/debugfs/logdump.c
++++ e2fsprogs-1.42.9/debugfs/logdump.c
+@@ -273,42 +273,43 @@ print_usage:
+
+
+ static int read_journal_block(const char *cmd, struct journal_source *source,
+- off_t offset, char *buf, int size,
+- unsigned int *got)
++ off_t offset, char *buf, unsigned int size)
+ {
+ int retval;
++ unsigned int got;
+
+ if (source->where == JOURNAL_IS_EXTERNAL) {
+ if (lseek(source->fd, offset, SEEK_SET) < 0) {
+ retval = errno;
+- com_err(cmd, retval, "while seeking in reading journal");
+- return retval;
++ goto seek_err;
+ }
+ retval = read(source->fd, buf, size);
+- if (retval >= 0) {
+- *got = retval;
+- retval = 0;
+- } else
++ if (retval < 0) {
+ retval = errno;
++ goto read_err;
++ }
++ got = retval;
++ retval = 0;
+ } else {
+ retval = ext2fs_file_lseek(source->file, offset,
+ EXT2_SEEK_SET, NULL);
+ if (retval) {
++ seek_err:
+ com_err(cmd, retval, "while seeking in reading journal");
+ return retval;
+ }
+-
+- retval = ext2fs_file_read(source->file, buf, size, got);
++ retval = ext2fs_file_read(source->file, buf, size, &got);
++ if (retval) {
++ read_err:
++ com_err(cmd, retval, "while reading journal");
++ return retval;
++ }
+ }
+-
+- if (retval)
+- com_err(cmd, retval, "while reading journal");
+- else if (*got != (unsigned int) size) {
+- com_err(cmd, 0, "short read (read %d, expected %d) "
+- "while reading journal", *got, size);
++ if (got != size) {
++ com_err(cmd, 0, "short read (read %u, expected %u) "
++ "while reading journal", got, size);
+ retval = -1;
+ }
+-
+ return retval;
+ }
+
+@@ -338,7 +339,6 @@ static void dump_journal(char *cmdname,
+ char buf[8192];
+ journal_superblock_t *jsb;
+ unsigned int blocksize = 1024;
+- unsigned int got;
+ int retval;
+ __u32 magic, sequence, blocktype;
+ journal_header_t *header;
+@@ -347,8 +347,7 @@ static void dump_journal(char *cmdname,
+ unsigned int blocknr = 0;
+
+ /* First, check to see if there's an ext2 superblock header */
+- retval = read_journal_block(cmdname, source, 0,
+- buf, 2048, &got);
++ retval = read_journal_block(cmdname, source, 0, buf, 2048);
+ if (retval)
+ return;
+
+@@ -377,7 +376,7 @@ static void dump_journal(char *cmdname,
+ /* Next, read the journal superblock */
+
+ retval = read_journal_block(cmdname, source, blocknr*blocksize,
+- jsb_buffer, 1024, &got);
++ jsb_buffer, 1024);
+ if (retval)
+ return;
+
+@@ -401,8 +400,8 @@ static void dump_journal(char *cmdname,
+ while (1) {
+ retval = read_journal_block(cmdname, source,
+ blocknr*blocksize, buf,
+- blocksize, &got);
+- if (retval || got != blocksize)
++ blocksize);
++ if (retval)
+ return;
+
+ header = (journal_header_t *) buf;
+@@ -576,7 +575,6 @@ static void dump_metadata_block(FILE *ou
+ int blocksize,
+ tid_t transaction)
+ {
+- unsigned int got;
+ int retval;
+ char buf[8192];
+
+@@ -612,7 +610,7 @@ static void dump_metadata_block(FILE *ou
+
+ retval = read_journal_block("logdump", source,
+ blocksize * log_blocknr,
+- buf, blocksize, &got);
++ buf, blocksize);
+ if (retval)
+ return;
+
+--- e2fsprogs-1.42.9.orig/debugfs/set_fields.c
++++ e2fsprogs-1.42.9/debugfs/set_fields.c
+@@ -150,6 +150,8 @@ static struct field_set_info super_field
+ { "usr_quota_inum", &set_sb.s_usr_quota_inum, NULL, 4, parse_uint },
+ { "grp_quota_inum", &set_sb.s_grp_quota_inum, NULL, 4, parse_uint },
+ { "overhead_blocks", &set_sb.s_overhead_blocks, NULL, 4, parse_uint },
++ { "backup_bgs", &set_sb.s_backup_bgs[0], NULL, 4, parse_uint,
++ FLAG_ARRAY, 2 },
+ { "checksum", &set_sb.s_checksum, NULL, 4, parse_uint },
+ { 0, 0, 0, 0 }
+ };
+--- e2fsprogs-1.42.9.orig/debugfs/util.c
++++ e2fsprogs-1.42.9/debugfs/util.c
+@@ -201,7 +201,7 @@ char *time_to_string(__u32 cl)
+ tz = ss_safe_getenv("TZ");
+ if (!tz)
+ tz = "";
+- do_gmt = !strcmp(tz, "GMT");
++ do_gmt = !strcmp(tz, "GMT") | !strcmp(tz, "GMT0");
+ }
+
+ return asctime((do_gmt) ? gmtime(&t) : localtime(&t));
+@@ -222,14 +222,18 @@ time_t string_to_time(const char *arg)
+ }
+ if (arg[0] == '@') {
+ /* interpret it as an integer */
+- ret = strtoul(arg+1, &tmp, 0);
++ arg++;
++ fallback:
++ ret = strtoul(arg, &tmp, 0);
+ if (*tmp)
+ return ((time_t) -1);
+ return ret;
+ }
+ memset(&ts, 0, sizeof(ts));
+ #ifdef HAVE_STRPTIME
+- strptime(arg, "%Y%m%d%H%M%S", &ts);
++ tmp = strptime(arg, "%Y%m%d%H%M%S", &ts);
++ if (tmp == NULL)
++ goto fallback;
+ #else
+ sscanf(arg, "%4d%2d%2d%2d%2d%2d", &ts.tm_year, &ts.tm_mon,
+ &ts.tm_mday, &ts.tm_hour, &ts.tm_min, &ts.tm_sec);
+@@ -241,13 +245,9 @@ time_t string_to_time(const char *arg)
+ ts.tm_mday = 0;
+ #endif
+ ts.tm_isdst = -1;
+- ret = mktime(&ts);
+- if (ts.tm_mday == 0 || ret == ((time_t) -1)) {
+- /* Try it as an integer... */
+- ret = strtoul(arg, &tmp, 0);
+- if (*tmp)
+- return ((time_t) -1);
+- }
++ ret = ts.tm_sec + ts.tm_min*60 + ts.tm_hour*3600 + ts.tm_yday*86400 +
++ (ts.tm_year-70)*31536000 + ((ts.tm_year-69)/4)*86400 -
++ ((ts.tm_year-1)/100)*86400 + ((ts.tm_year+299)/400)*86400;
+ return ret;
+ }
+
+--- e2fsprogs-1.42.9.orig/e2fsck/Makefile.in
++++ e2fsprogs-1.42.9/e2fsck/Makefile.in
+@@ -16,19 +16,20 @@ MANPAGES= e2fsck.8
+ FMANPAGES= e2fsck.conf.5
+
+ LIBS= $(LIBQUOTA) $(LIBEXT2FS) $(LIBCOM_ERR) $(LIBBLKID) $(LIBUUID) \
+- $(LIBINTL) $(LIBE2P)
++ $(LIBINTL) $(LIBE2P) $(SYSLIBS)
+ DEPLIBS= $(DEPLIBQUOTA) $(LIBEXT2FS) $(DEPLIBCOM_ERR) $(DEPLIBBLKID) \
+ $(DEPLIBUUID) $(DEPLIBE2P)
+
+ STATIC_LIBS= $(STATIC_LIBQUOTA) $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR) \
+- $(STATIC_LIBBLKID) $(STATIC_LIBUUID) $(LIBINTL) $(STATIC_LIBE2P)
++ $(STATIC_LIBBLKID) $(STATIC_LIBUUID) $(LIBINTL) $(STATIC_LIBE2P) \
++ $(SYSLIBS)
+ STATIC_DEPLIBS= $(DEPSTATIC_LIBQUOTA) $(STATIC_LIBEXT2FS) \
+ $(DEPSTATIC_LIBCOM_ERR) $(DEPSTATIC_LIBBLKID) \
+ $(DEPSTATIC_LIBUUID) $(DEPSTATIC_LIBE2P)
+
+ PROFILED_LIBS= $(PROFILED_LIBQUOTA) $(PROFILED_LIBEXT2FS) \
+ $(PROFILED_LIBCOM_ERR) $(PROFILED_LIBBLKID) $(PROFILED_LIBUUID) \
+- $(PROFILED_LIBE2P) $(LIBINTL)
++ $(PROFILED_LIBE2P) $(LIBINTL) $(SYSLIBS)
+ PROFILED_DEPLIBS= $(DEPPROFILED_LIBQUOTA) $(PROFILED_LIBEXT2FS) \
+ $(DEPPROFILED_LIBCOM_ERR) $(DEPPROFILED_LIBBLKID) \
+ $(DEPPROFILED_LIBUUID) $(DEPPROFILED_LIBE2P)
+@@ -153,26 +154,27 @@ tst_problem: $(srcdir)/problem.c $(srcdi
+ $(DEPLIBCOM_ERR)
+ $(Q) $(CC) $(BUILD_LDFLAGS) $(ALL_CFLAGS) -o tst_problem \
+ $(srcdir)/problem.c -DUNITTEST $(LIBEXT2FS) $(LIBCOM_ERR) \
+- $(LIBINTL)
++ $(LIBINTL) $(SYSLIBS)
+
+ tst_crc32: $(srcdir)/crc32.c $(LIBEXT2FS) $(DEPLIBCOM_ERR)
+ $(Q) $(CC) $(BUILD_LDFLAGS) $(ALL_CFLAGS) -o tst_crc32 $(srcdir)/crc32.c \
+- -DUNITTEST $(LIBEXT2FS) $(LIBCOM_ERR)
++ -DUNITTEST $(LIBEXT2FS) $(LIBCOM_ERR) $(SYSLIBS)
+
+ tst_refcount: ea_refcount.c $(DEPLIBCOM_ERR)
+ $(E) " LD $@"
+ $(Q) $(CC) -o tst_refcount $(srcdir)/ea_refcount.c \
+- $(ALL_CFLAGS) -DTEST_PROGRAM $(LIBCOM_ERR) $(LIBEXT2FS)
++ $(ALL_CFLAGS) -DTEST_PROGRAM $(LIBCOM_ERR) $(LIBEXT2FS) \
++ $(SYSLIBS)
+
+ tst_logfile: $(srcdir)/logfile.c
+ $(E) " LD $@"
+ $(Q) $(CC) -o tst_logfile $(srcdir)/logfile.c $(ALL_CFLAGS) \
+- -DTEST_PROGRAM
++ -DTEST_PROGRAM $(SYSLIBS)
+
+ tst_region: region.c $(DEPLIBCOM_ERR)
+ $(E) " LD $@"
+ $(Q) $(CC) -o tst_region $(srcdir)/region.c \
+- $(ALL_CFLAGS) -DTEST_PROGRAM $(LIBCOM_ERR)
++ $(ALL_CFLAGS) -DTEST_PROGRAM $(LIBCOM_ERR) $(SYSLIBS)
+
+ check:: tst_refcount tst_region tst_crc32 tst_problem
+ LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_refcount
+--- e2fsprogs-1.42.9.orig/e2fsck/badblocks.c
++++ e2fsprogs-1.42.9/e2fsck/badblocks.c
+@@ -111,6 +111,8 @@ void read_bad_blocks_file(e2fsck_t ctx,
+
+ fatal:
+ ctx->flags |= E2F_FLAG_ABORT;
++ if (bb_list)
++ ext2fs_badblocks_list_free(bb_list);
+ return;
+
+ }
+--- e2fsprogs-1.42.9.orig/e2fsck/dirinfo.c
++++ e2fsprogs-1.42.9/e2fsck/dirinfo.c
+@@ -42,6 +42,7 @@ static void setup_tdb(e2fsck_t ctx, ext2
+ struct dir_info_db *db = ctx->dir_info;
+ unsigned int threshold;
+ errcode_t retval;
++ mode_t save_umask;
+ char *tdb_dir, uuid[40];
+ int fd, enable;
+
+@@ -62,7 +63,9 @@ static void setup_tdb(e2fsck_t ctx, ext2
+
+ uuid_unparse(ctx->fs->super->s_uuid, uuid);
+ sprintf(db->tdb_fn, "%s/%s-dirinfo-XXXXXX", tdb_dir, uuid);
++ save_umask = umask(077);
+ fd = mkstemp(db->tdb_fn);
++ umask(save_umask);
+ if (fd < 0) {
+ db->tdb = NULL;
+ return;
+--- e2fsprogs-1.42.9.orig/e2fsck/e2fsck.conf.5.in
++++ e2fsprogs-1.42.9/e2fsck/e2fsck.conf.5.in
+@@ -97,9 +97,8 @@ incorrectly set at the time when e2fsck
+ Historically this was usually due to some distributions
+ having buggy init scripts and/or installers that didn't
+ correctly detect this case and take appropriate
+-countermeasures. However, it's still possible, despite the
+-best efforts of init script and installer authors to not be
+-able to detect this misconfiguration, usually due to a
++countermeasures. Unfortunately, this is occasionally
++true even today, usually due to a
+ buggy or misconfigured virtualization manager or the
+ installer not having access to a network time server
+ during the installation process. So by default, we allow
+--- e2fsprogs-1.42.9.orig/e2fsck/message.c
++++ e2fsprogs-1.42.9/e2fsck/message.c
+@@ -226,7 +226,8 @@ static void print_time(FILE *f, time_t t
+ time_str = getenv("TZ");
+ if (!time_str)
+ time_str = "";
+- do_gmt = !strcmp(time_str, "GMT0");
++ do_gmt = !strcmp(time_str, "GMT") ||
++ !strcmp(time_str, "GMT0");
+ }
+ #endif
+ time_str = asctime((do_gmt > 0) ? gmtime(&t) : localtime(&t));
+--- e2fsprogs-1.42.9.orig/e2fsck/pass1.c
++++ e2fsprogs-1.42.9/e2fsck/pass1.c
+@@ -546,9 +546,9 @@ void e2fsck_pass1(e2fsck_t ctx)
+ __u64 max_sizes;
+ ext2_filsys fs = ctx->fs;
+ ext2_ino_t ino = 0;
+- struct ext2_inode *inode;
+- ext2_inode_scan scan;
+- char *block_buf;
++ struct ext2_inode *inode = NULL;
++ ext2_inode_scan scan = NULL;
++ char *block_buf = NULL;
+ #ifdef RESOURCE_TRACK
+ struct resource_track rtrack;
+ #endif
+@@ -662,8 +662,7 @@ void e2fsck_pass1(e2fsck_t ctx)
+ if (pctx.errcode) {
+ fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
+ ctx->flags |= E2F_FLAG_ABORT;
+- ext2fs_free_mem(&inode);
+- return;
++ goto endit;
+ }
+
+ /*
+@@ -686,8 +685,7 @@ void e2fsck_pass1(e2fsck_t ctx)
+ if (pctx.errcode) {
+ fix_problem(ctx, PR_1_CONVERT_SUBCLUSTER, &pctx);
+ ctx->flags |= E2F_FLAG_ABORT;
+- ext2fs_free_mem(&inode);
+- return;
++ goto endit;
+ }
+ block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
+ "block interate buffer");
+@@ -699,18 +697,16 @@ void e2fsck_pass1(e2fsck_t ctx)
+ if (pctx.errcode) {
+ fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
+ ctx->flags |= E2F_FLAG_ABORT;
+- ext2fs_free_mem(&block_buf);
+- ext2fs_free_mem(&inode);
+- return;
++ goto endit;
+ }
+ ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
+ ctx->stashed_inode = inode;
+ scan_struct.ctx = ctx;
+ scan_struct.block_buf = block_buf;
+ ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
+- if (ctx->progress)
+- if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
+- return;
++ if (ctx->progress && ((ctx->progress)(ctx, 1, 0,
++ ctx->fs->group_desc_count)))
++ goto endit;
+ if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
+ (fs->super->s_mtime < fs->super->s_inodes_count))
+ busted_fs_time = 1;
+@@ -742,7 +738,7 @@ void e2fsck_pass1(e2fsck_t ctx)
+ if (pctx.errcode) {
+ fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
+ ctx->flags |= E2F_FLAG_ABORT;
+- return;
++ goto endit;
+ }
+ if (!ino)
+ break;
+@@ -756,7 +752,7 @@ void e2fsck_pass1(e2fsck_t ctx)
+ pctx.num = inode->i_links_count;
+ fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
+ ctx->flags |= E2F_FLAG_ABORT;
+- return;
++ goto endit;
+ }
+ }
+
+@@ -846,7 +842,7 @@ void e2fsck_pass1(e2fsck_t ctx)
+ pctx.num = 4;
+ fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
+ ctx->flags |= E2F_FLAG_ABORT;
+- return;
++ goto endit;
+ }
+ pb.ino = EXT2_BAD_INO;
+ pb.num_blocks = pb.last_block = 0;
+@@ -863,12 +859,12 @@ void e2fsck_pass1(e2fsck_t ctx)
+ if (pctx.errcode) {
+ fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
+ ctx->flags |= E2F_FLAG_ABORT;
+- return;
++ goto endit;
+ }
+ if (pb.bbcheck)
+ if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
+ ctx->flags |= E2F_FLAG_ABORT;
+- return;
++ goto endit;
+ }
+ ext2fs_mark_inode_bitmap2(ctx->inode_used_map, ino);
+ clear_problem_context(&pctx);
+@@ -1146,17 +1142,18 @@ void e2fsck_pass1(e2fsck_t ctx)
+ check_blocks(ctx, &pctx, block_buf);
+
+ if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+- return;
++ goto endit;
+
+ if (process_inode_count >= ctx->process_inode_size) {
+ process_inodes(ctx, block_buf);
+
+ if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+- return;
++ goto endit;
+ }
+ }
+ process_inodes(ctx, block_buf);
+ ext2fs_close_inode_scan(scan);
++ scan = NULL;
+
+ /*
+ * If any extended attribute blocks' reference counts need to
+@@ -1195,7 +1192,7 @@ void e2fsck_pass1(e2fsck_t ctx)
+ if (!fix_problem(ctx, PR_1_RESIZE_INODE_CREATE,
+ &pctx)) {
+ ctx->flags |= E2F_FLAG_ABORT;
+- return;
++ goto endit;
+ }
+ pctx.errcode = 0;
+ }
+@@ -1233,10 +1230,15 @@ void e2fsck_pass1(e2fsck_t ctx)
+ endit:
+ e2fsck_use_inode_shortcuts(ctx, 0);
+
+- ext2fs_free_mem(&block_buf);
+- ext2fs_free_mem(&inode);
++ if (scan)
++ ext2fs_close_inode_scan(scan);
++ if (block_buf)
++ ext2fs_free_mem(&block_buf);
++ if (inode)
++ ext2fs_free_mem(&inode);
+
+- print_resource_track(ctx, _("Pass 1"), &rtrack, ctx->fs->io);
++ if ((ctx->flags & E2F_FLAG_SIGNAL_MASK) == 0)
++ print_resource_track(ctx, _("Pass 1"), &rtrack, ctx->fs->io);
+ }
+
+ /*
+--- e2fsprogs-1.42.9.orig/e2fsck/pass5.c
++++ e2fsprogs-1.42.9/e2fsck/pass5.c
+@@ -207,7 +207,6 @@ static void check_block_bitmaps(e2fsck_t
+ int fixit, had_problem;
+ errcode_t retval;
+ int csum_flag;
+- int skip_group = 0;
+ int old_desc_blocks = 0;
+ int count = 0;
+ int cmp_block = 0;
+@@ -260,9 +259,6 @@ redo_counts:
+ had_problem = 0;
+ save_problem = 0;
+ pctx.blk = pctx.blk2 = NO_BLK;
+- if (csum_flag &&
+- (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT)))
+- skip_group++;
+ for (i = B2C(fs->super->s_first_data_block);
+ i < ext2fs_blocks_count(fs->super);
+ i += EXT2FS_CLUSTER_RATIO(fs)) {
+@@ -293,15 +289,11 @@ redo_counts:
+ actual_buf);
+ if (retval)
+ goto no_optimize;
+- if (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT))
+- memset(bitmap_buf, 0, nbytes);
+- else {
+- retval = ext2fs_get_block_bitmap_range2(fs->block_map,
+- B2C(i), fs->super->s_clusters_per_group,
+- bitmap_buf);
+- if (retval)
+- goto no_optimize;
+- }
++ retval = ext2fs_get_block_bitmap_range2(fs->block_map,
++ B2C(i), fs->super->s_clusters_per_group,
++ bitmap_buf);
++ if (retval)
++ goto no_optimize;
+ if (memcmp(actual_buf, bitmap_buf, nbytes) != 0)
+ goto no_optimize;
+ n = ext2fs_bitcount(actual_buf, nbytes);
+@@ -311,73 +303,7 @@ redo_counts:
+ goto next_group;
+ no_optimize:
+
+- if (skip_group) {
+- if (first_block_in_bg) {
+- super_blk = 0;
+- old_desc_blk = 0;
+- new_desc_blk = 0;
+- ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
+- &old_desc_blk, &new_desc_blk, 0);
+-
+- if (fs->super->s_feature_incompat &
+- EXT2_FEATURE_INCOMPAT_META_BG)
+- old_desc_blocks =
+- fs->super->s_first_meta_bg;
+- else
+- old_desc_blocks = fs->desc_blocks +
+- fs->super->s_reserved_gdt_blocks;
+-
+- count = 0;
+- cmp_block = fs->super->s_clusters_per_group;
+- if (group == (int)fs->group_desc_count - 1)
+- cmp_block = EXT2FS_NUM_B2C(fs,
+- ext2fs_group_blocks_count(fs, group));
+- }
+-
+- bitmap = 0;
+- if (EQ_CLSTR(i, super_blk) ||
+- (old_desc_blk && old_desc_blocks &&
+- GE_CLSTR(i, old_desc_blk) &&
+- LE_CLSTR(i, old_desc_blk + old_desc_blocks-1)) ||
+- (new_desc_blk && EQ_CLSTR(i, new_desc_blk)) ||
+- EQ_CLSTR(i, ext2fs_block_bitmap_loc(fs, group)) ||
+- EQ_CLSTR(i, ext2fs_inode_bitmap_loc(fs, group)) ||
+- (GE_CLSTR(i, ext2fs_inode_table_loc(fs, group)) &&
+- LE_CLSTR(i, (ext2fs_inode_table_loc(fs, group) +
+- fs->inode_blocks_per_group - 1)))) {
+- bitmap = 1;
+- actual = (actual != 0);
+- count++;
+- cmp_block--;
+- } else if ((EXT2FS_B2C(fs, i) - count -
+- EXT2FS_B2C(fs, fs->super->s_first_data_block)) %
+- fs->super->s_clusters_per_group == 0) {
+- /*
+- * When the compare data blocks in block bitmap
+- * are 0, count the free block,
+- * skip the current block group.
+- */
+- if (ext2fs_test_block_bitmap_range2(
+- ctx->block_found_map,
+- EXT2FS_B2C(fs, i),
+- cmp_block)) {
+- /*
+- * -1 means to skip the current block
+- * group.
+- */
+- blocks = fs->super->s_clusters_per_group - 1;
+- group_free = cmp_block;
+- free_blocks += cmp_block;
+- /*
+- * The current block group's last block
+- * is set to i.
+- */
+- i += EXT2FS_C2B(fs, cmp_block - 1);
+- bitmap = 1;
+- goto do_counts;
+- }
+- }
+- } else if (redo_flag)
++ if (redo_flag)
+ bitmap = actual;
+ else
+ bitmap = ext2fs_fast_test_block_bitmap2(fs->block_map, i);
+@@ -396,14 +322,15 @@ redo_counts:
+ */
+ problem = PR_5_BLOCK_USED;
+
+- if (skip_group) {
++ if (ext2fs_bg_flags_test(fs, group,
++ EXT2_BG_BLOCK_UNINIT)) {
+ struct problem_context pctx2;
+ pctx2.blk = i;
+ pctx2.group = group;
+- if (fix_problem(ctx, PR_5_BLOCK_UNINIT,&pctx2)){
+- ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
+- skip_group = 0;
+- }
++ if (fix_problem(ctx, PR_5_BLOCK_UNINIT,
++ &pctx2))
++ ext2fs_bg_flags_clear(fs, group,
++ EXT2_BG_BLOCK_UNINIT);
+ }
+ }
+ if (pctx.blk == NO_BLK) {
+@@ -457,16 +384,10 @@ redo_counts:
+ group ++;
+ blocks = 0;
+ group_free = 0;
+- skip_group = 0;
+ if (ctx->progress)
+ if ((ctx->progress)(ctx, 5, group,
+ fs->group_desc_count*2))
+ goto errout;
+- if (csum_flag &&
+- (i != ext2fs_blocks_count(fs->super)-1) &&
+- ext2fs_bg_flags_test(fs, group,
+- EXT2_BG_BLOCK_UNINIT))
+- skip_group++;
+ }
+ }
+ if (pctx.blk != NO_BLK)
+--- e2fsprogs-1.42.9.orig/e2fsck/problem.c
++++ e2fsprogs-1.42.9/e2fsck/problem.c
+@@ -119,11 +119,13 @@ static struct e2fsck_problem problem_tab
+
+ /* Superblock corrupt */
+ { PR_0_SB_CORRUPT,
+- N_("\nThe @S could not be read or does not describe a correct ext2\n"
+- "@f. If the @v is valid and it really contains an ext2\n"
++ N_("\nThe @S could not be read or does not describe a valid ext2/ext3/ext4\n"
++ "@f. If the @v is valid and it really contains an ext2/ext3/ext4\n"
+ "@f (and not swap or ufs or something else), then the @S\n"
+ "is corrupt, and you might try running e2fsck with an alternate @S:\n"
+- " e2fsck -b %S <@v>\n\n"),
++ " e2fsck -b 8193 <@v>\n"
++ " or\n"
++ " e2fsck -b 32768 <@v>\n\n"),
+ PROMPT_NONE, PR_FATAL },
+
+ /* Filesystem size is wrong */
+--- e2fsprogs-1.42.9.orig/e2fsck/profile.c
++++ e2fsprogs-1.42.9/e2fsck/profile.c
+@@ -320,6 +320,7 @@ profile_init(const char **files, profile
+ for (fs = files; !PROFILE_LAST_FILESPEC(*fs); fs++) {
+ if (array)
+ free_list(array);
++ array = NULL;
+ retval = get_dirlist(*fs, &array);
+ if (retval == 0) {
+ if (!array)
+@@ -1544,7 +1545,7 @@ profile_get_integer(profile_t profile, c
+ /* Empty string is no good. */
+ return PROF_BAD_INTEGER;
+ errno = 0;
+- ret_long = strtol (value, &end_value, 10);
++ ret_long = strtol(value, &end_value, 0);
+
+ /* Overflow or underflow. */
+ if ((ret_long == LONG_MIN || ret_long == LONG_MAX) && errno != 0)
+@@ -1586,7 +1587,7 @@ profile_get_uint(profile_t profile, cons
+ /* Empty string is no good. */
+ return PROF_BAD_INTEGER;
+ errno = 0;
+- ret_long = strtoul (value, &end_value, 10);
++ ret_long = strtoul(value, &end_value, 0);
+
+ /* Overflow or underflow. */
+ if ((ret_long == ULONG_MAX) && errno != 0)
+--- e2fsprogs-1.42.9.orig/e2fsck/quota.c
++++ e2fsprogs-1.42.9/e2fsck/quota.c
+@@ -22,14 +22,18 @@ static void move_quota_inode(ext2_filsys
+ ext2_ino_t to_ino, int qtype)
+ {
+ struct ext2_inode inode;
++ errcode_t retval;
+ char qf_name[QUOTA_NAME_LEN];
+
+ /* We need the inode bitmap to be loaded */
+ if (ext2fs_read_bitmaps(fs))
+ return;
+
+- if (ext2fs_read_inode(fs, from_ino, &inode))
++ retval = ext2fs_read_inode(fs, from_ino, &inode);
++ if (retval) {
++ com_err("ext2fs_read_inode", retval, _("in move_quota_inode"));
+ return;
++ }
+
+ inode.i_links_count = 1;
+ inode.i_mode = LINUX_S_IFREG | 0600;
+@@ -38,7 +42,13 @@ static void move_quota_inode(ext2_filsys
+ EXT3_FEATURE_INCOMPAT_EXTENTS)
+ inode.i_flags |= EXT4_EXTENTS_FL;
+
+- ext2fs_write_new_inode(fs, to_ino, &inode);
++ retval = ext2fs_write_new_inode(fs, to_ino, &inode);
++ if (retval) {
++ com_err("ext2fs_write_new_inode", retval,
++ _("in move_quota_inode"));
++ return;
++ }
++
+ /* unlink the old inode */
+ quota_get_qf_name(qtype, QFMT_VFS_V1, qf_name);
+ ext2fs_unlink(fs, EXT2_ROOT_INO, qf_name, from_ino, 0);
+--- e2fsprogs-1.42.9.orig/intl/Makefile.in
++++ e2fsprogs-1.42.9/intl/Makefile.in
+@@ -59,6 +59,20 @@ mkinstalldirs = $(SHELL) $(MKINSTALLDIRS
+ @ifNotGNUmake@ E = @E@
+ @ifNotGNUmake@ Q = @Q@
+
++@ifGNUmake@ CHECK=sparse
++@ifGNUmake@ CHECK_OPTS=-Wsparse-all -Wno-transparent-union -Wno-return-void -Wno-undef -Wno-non-pointer-null
++@ifGNUmake@ ifeq ("$(C)", "2")
++@ifGNUmake@ CHECK_CMD=$(CHECK) $(CHECK_OPTS) -Wbitwise -D__CHECK_ENDIAN__
++@ifGNUmake@ else
++@ifGNUmake@ ifeq ("$(C)", "1")
++@ifGNUmake@ CHECK_CMD=$(CHECK) $(CHECK_OPTS)
++@ifGNUmake@ else
++@ifGNUmake@ CHECK_CMD=@true
++@ifGNUmake@ endif
++@ifGNUmake@ endif
++
++@ifNotGNUmake@ CHECK_CMD=@true
++
+ l = @INTL_LIBTOOL_SUFFIX_PREFIX@
+
+ AR = ar
+--- e2fsprogs-1.42.9.orig/lib/blkid/cache.c
++++ e2fsprogs-1.42.9/lib/blkid/cache.c
+@@ -167,8 +167,6 @@ void blkid_gc_cache(blkid_cache cache)
+
+ list_for_each_safe(p, pnext, &cache->bic_devs) {
+ blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs);
+- if (!p)
+- break;
+ if (stat(dev->bid_name, &st) < 0) {
+ DBG(DEBUG_CACHE,
+ printf("freeing %s\n", dev->bid_name));
+--- e2fsprogs-1.42.9.orig/lib/blkid/devname.c
++++ e2fsprogs-1.42.9/lib/blkid/devname.c
+@@ -91,8 +91,6 @@ blkid_dev blkid_get_dev(blkid_cache cach
+ */
+ list_for_each_safe(p, pnext, &cache->bic_devs) {
+ blkid_dev dev2;
+- if (!p)
+- break;
+ dev2 = list_entry(p, struct blkid_struct_dev, bid_devs);
+ if (dev2->bid_flags & BLKID_BID_FL_VERIFIED)
+ continue;
+--- e2fsprogs-1.42.9.orig/lib/blkid/probe.c
++++ e2fsprogs-1.42.9/lib/blkid/probe.c
+@@ -243,7 +243,7 @@ static int check_for_modules(const char
+ return (0);
+ }
+
+-static int linux_version_code()
++static int linux_version_code(void)
+ {
+ #ifdef __linux__
+ struct utsname ut;
+@@ -586,7 +586,7 @@ static int probe_fat(struct blkid_probe
+ int count;
+
+ next_sect_off = (next - 2) * vs->vs_cluster_size;
+- next_off = (start_data_sect + next_sect_off) *
++ next_off = (__u64) (start_data_sect + next_sect_off) *
+ sector_size;
+
+ dir = (struct vfat_dir_entry *)
+@@ -601,7 +601,9 @@ static int probe_fat(struct blkid_probe
+ break;
+
+ /* get FAT entry */
+- fat_entry_off = (reserved * sector_size) +
++ fat_entry_off =
++ ((unsigned int) reserved *
++ (unsigned int) sector_size) +
+ (next * sizeof(__u32));
+ buf = get_buffer(probe, fat_entry_off, buf_size);
+ if (buf == NULL)
+@@ -1003,7 +1005,8 @@ static int probe_udf(struct blkid_probe
+ (block sizes larger than 2K will be null padded) */
+ for (bs = 1; bs < 16; bs++) {
+ isosb = (struct iso_volume_descriptor *)
+- get_buffer(probe, bs*2048+32768, sizeof(isosb));
++ get_buffer(probe, (blkid_loff_t) bs*2048+32768,
++ sizeof(*isosb));
+ if (!isosb)
+ return 1;
+ if (isosb->vd_id[0])
+@@ -1015,7 +1018,7 @@ static int probe_udf(struct blkid_probe
+ if (j > 1) {
+ isosb = (struct iso_volume_descriptor *)
+ get_buffer(probe, j*bs*2048+32768,
+- sizeof(isosb));
++ sizeof(*isosb));
+ if (!isosb)
+ return 1;
+ }
+@@ -1223,7 +1226,7 @@ static int probe_hfsplus(struct blkid_pr
+ off = (alloc_first_block * 512) +
+ (embed_first_block * alloc_block_size);
+ buf = get_buffer(probe, off + (id->bim_kboff * 1024),
+- sizeof(sbd));
++ sizeof(*sbd));
+ if (!buf)
+ return 1;
+
+@@ -1247,7 +1250,7 @@ static int probe_hfsplus(struct blkid_pr
+ memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
+ cat_block = blkid_be32(extents[0].start_block);
+
+- buf = get_buffer(probe, off + (cat_block * blocksize), 0x2000);
++ buf = get_buffer(probe, off + ((__u64) cat_block * blocksize), 0x2000);
+ if (!buf)
+ return 0;
+
+@@ -1278,7 +1281,7 @@ static int probe_hfsplus(struct blkid_pr
+ if (ext == HFSPLUS_EXTENT_COUNT)
+ return 0;
+
+- leaf_off = (ext_block_start + leaf_block) * blocksize;
++ leaf_off = (__u64) (ext_block_start + leaf_block) * blocksize;
+
+ buf = get_buffer(probe, off + leaf_off, leaf_node_size);
+ if (!buf)
+@@ -1360,7 +1363,7 @@ static int probe_lvm2(struct blkid_probe
+ return 1;
+ }
+
+- for (i=0, b=1, p=uuid, q= (char *) label->pv_uuid; i <= 32;
++ for (i=0, b=1, p=uuid, q= (char *) label->pv_uuid; i < LVM2_ID_LEN;
+ i++, b <<= 1) {
+ if (b & 0x4444440)
+ *p++ = '-';
+@@ -1580,7 +1583,7 @@ try_again:
+ continue;
+
+ idx = id->bim_kboff + (id->bim_sboff >> 10);
+- buf = get_buffer(&probe, idx << 10, 1024);
++ buf = get_buffer(&probe, (__u64) idx << 10, 1024);
+ if (!buf)
+ continue;
+
+--- e2fsprogs-1.42.9.orig/lib/blkid/save.c
++++ e2fsprogs-1.42.9/lib/blkid/save.c
+@@ -94,8 +94,10 @@ int blkid_flush_cache(blkid_cache cache)
+ if (ret == 0 && S_ISREG(st.st_mode)) {
+ tmp = malloc(strlen(filename) + 8);
+ if (tmp) {
++ mode_t save_umask = umask(022);
+ sprintf(tmp, "%s-XXXXXX", filename);
+ fd = mkstemp(tmp);
++ umask(save_umask);
+ if (fd >= 0) {
+ file = fdopen(fd, "w");
+ opened = tmp;
+@@ -134,7 +136,7 @@ int blkid_flush_cache(blkid_cache cache)
+ fclose(file);
+ if (opened != filename) {
+ if (ret < 0) {
+- unlink(opened);
++ (void) unlink(opened);
+ DBG(DEBUG_SAVE,
+ printf("unlinked temp cache %s\n", opened));
+ } else {
+@@ -147,7 +149,8 @@ int blkid_flush_cache(blkid_cache cache)
+ link(filename, backup);
+ free(backup);
+ }
+- rename(opened, filename);
++ if (rename(opened, filename) < 0)
++ (void) unlink(opened);
+ DBG(DEBUG_SAVE,
+ printf("moved temp cache %s\n", opened));
+ }
+--- e2fsprogs-1.42.9.orig/lib/config.h.in
++++ e2fsprogs-1.42.9/lib/config.h.in
+@@ -103,6 +103,9 @@
+ /* Define to 1 if Ext2 ioctls present */
+ #undef HAVE_EXT2_IOCTLS
+
++/* Define to 1 if you have the `fadvise64' function. */
++#undef HAVE_FADVISE64
++
+ /* Define to 1 if you have the `fallocate' function. */
+ #undef HAVE_FALLOCATE
+
+@@ -121,6 +124,9 @@
+ /* Define to 1 if you have the `ftruncate64' function. */
+ #undef HAVE_FTRUNCATE64
+
++/* Define to 1 if you have the `futimes' function. */
++#undef HAVE_FUTIMES
++
+ /* Define to 1 if you have the `fwprintf' function. */
+ #undef HAVE_FWPRINTF
+
+@@ -197,6 +203,9 @@
+ /* Define to 1 if you have the <linux/fd.h> header file. */
+ #undef HAVE_LINUX_FD_H
+
++/* Define to 1 if you have the <linux/loop.h> header file. */
++#undef HAVE_LINUX_LOOP_H
++
+ /* Define to 1 if you have the <linux/major.h> header file. */
+ #undef HAVE_LINUX_MAJOR_H
+
+@@ -281,6 +290,9 @@
+ /* Define to 1 if you have the `posix_fadvise' function. */
+ #undef HAVE_POSIX_FADVISE
+
++/* Define to 1 if you have the `posix_fadvise64' function. */
++#undef HAVE_POSIX_FADVISE64
++
+ /* Define to 1 if you have the `posix_memalign' function. */
+ #undef HAVE_POSIX_MEMALIGN
+
+@@ -381,6 +393,9 @@
+ /* Define to 1 if you have the `strtoull' function. */
+ #undef HAVE_STRTOULL
+
++/* Define to 1 if `st_atim' is a member of `struct stat'. */
++#undef HAVE_STRUCT_STAT_ST_ATIM
++
+ /* Define to 1 if you have the `sync_file_range' function. */
+ #undef HAVE_SYNC_FILE_RANGE
+
+@@ -620,4 +635,4 @@
+ <inttypes.h> don't define. */
+ #undef uintmax_t
+
+-#include "dirpaths.h"
++#include <dirpaths.h>
+--- e2fsprogs-1.42.9.orig/lib/e2p/feature.c
++++ e2fsprogs-1.42.9/lib/e2p/feature.c
+@@ -43,6 +43,8 @@ static struct feature feature_list[] = {
+ "lazy_bg" },
+ { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP,
+ "snapshot_bitmap" },
++ { E2P_FEATURE_COMPAT, EXT4_FEATURE_COMPAT_SPARSE_SUPER2,
++ "sparse_super2" },
+
+ { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER,
+ "sparse_super" },
+--- e2fsprogs-1.42.9.orig/lib/e2p/ls.c
++++ e2fsprogs-1.42.9/lib/e2p/ls.c
+@@ -368,6 +368,14 @@ void list_super2(struct ext2_super_block
+ fprintf(f, "type %u\n", sb->s_jnl_backup_type);
+ }
+ }
++ if (sb->s_backup_bgs[0] || sb->s_backup_bgs[1]) {
++ fprintf(f, "Backup block groups: ");
++ if (sb->s_backup_bgs[0])
++ fprintf(f, "%u ", sb->s_backup_bgs[0]);
++ if (sb->s_backup_bgs[1])
++ fprintf(f, "%u ", sb->s_backup_bgs[1]);
++ fputc('\n', f);
++ }
+ if (sb->s_snapshot_inum) {
+ fprintf(f, "Snapshot inode: %u\n",
+ sb->s_snapshot_inum);
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/Makefile.in
++++ e2fsprogs-1.42.9/lib/ext2fs/Makefile.in
+@@ -225,72 +225,72 @@ ext2fs.pc: $(srcdir)/ext2fs.pc.in $(top_
+ tst_badblocks: tst_badblocks.o $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR)
+ $(E) " LD $@"
+ $(Q) $(CC) -o tst_badblocks tst_badblocks.o $(STATIC_LIBEXT2FS) \
+- $(STATIC_LIBCOM_ERR)
++ $(STATIC_LIBCOM_ERR) $(SYSLIBS)
+
+ tst_icount: $(srcdir)/icount.c $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR)
+ $(E) " LD $@"
+ $(Q) $(CC) -o tst_icount $(srcdir)/icount.c -DDEBUG $(ALL_CFLAGS) \
+- $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR)
++ $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR) $(SYSLIBS)
+
+ tst_iscan: tst_iscan.o $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR)
+ $(E) " LD $@"
+ $(Q) $(CC) -o tst_iscan tst_iscan.o $(STATIC_LIBEXT2FS) \
+- $(STATIC_LIBCOM_ERR)
++ $(STATIC_LIBCOM_ERR) $(SYSLIBS)
+
+ tst_getsize: tst_getsize.o $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR)
+ $(E) " LD $@"
+ $(Q) $(CC) -o tst_getsize tst_getsize.o $(STATIC_LIBEXT2FS) \
+- $(STATIC_LIBCOM_ERR)
++ $(STATIC_LIBCOM_ERR) $(SYSLIBS)
+
+ tst_ismounted: $(srcdir)/ismounted.c $(STATIC_LIBEXT2FS) \
+ $(DEPSTATIC_LIBCOM_ERR)
+ $(E) " LD $@"
+ $(Q) $(CC) -o tst_ismounted $(srcdir)/ismounted.c \
+ $(STATIC_LIBEXT2FS) -DDEBUG $(ALL_CFLAGS) \
+- $(STATIC_LIBCOM_ERR)
++ $(STATIC_LIBCOM_ERR) $(SYSLIBS)
+
+ tst_byteswap: tst_byteswap.o $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR)
+ $(E) " LD $@"
+ $(Q) $(CC) -o tst_byteswap tst_byteswap.o $(STATIC_LIBEXT2FS) \
+- $(STATIC_LIBCOM_ERR)
++ $(STATIC_LIBCOM_ERR) $(SYSLIBS)
+
+ tst_bitops: tst_bitops.o $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR)
+ $(E) " LD $@"
+ $(Q) $(CC) -o tst_bitops tst_bitops.o $(ALL_CFLAGS) \
+- $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR)
++ $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR) $(SYSLIBS)
+
+ tst_getsectsize: tst_getsectsize.o $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR)
+ $(E) " LD $@"
+ $(Q) $(CC) -o tst_sectgetsize tst_getsectsize.o \
+- $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR)
++ $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR) $(SYSLIBS)
+
+ tst_types.o: $(srcdir)/tst_types.c ext2_types.h
+
+ tst_types: tst_types.o ext2_types.h
+ $(E) " LD $@"
+- $(Q) $(CC) -o tst_types tst_types.o
++ $(Q) $(CC) -o tst_types tst_types.o $(SYSLIBS)
+
+ tst_super_size.o: $(srcdir)/tst_super_size.c $(srcdir)/ext2_fs.h
+
+ tst_super_size: tst_super_size.o
+ $(E) " LD $@"
+- $(Q) $(CC) -o tst_super_size tst_super_size.o
++ $(Q) $(CC) -o tst_super_size tst_super_size.o $(SYSLIBS)
+
+ tst_fs_struct.o: $(srcdir)/tst_fs_struct.c $(srcdir)/ext2fs.h
+
+ tst_fs_struct: tst_fs_struct.o
+ $(E) " LD $@"
+- $(Q) $(CC) -o tst_fs_struct tst_fs_struct.o
++ $(Q) $(CC) -o tst_fs_struct tst_fs_struct.o $(SYSLIBS)
+
+ tst_inode_size.o: $(srcdir)/tst_inode_size.c $(srcdir)/ext2_fs.h
+
+ tst_inode_size: tst_inode_size.o
+ $(E) " LD $@"
+- $(Q) $(CC) -o tst_inode_size tst_inode_size.o
++ $(Q) $(CC) -o tst_inode_size tst_inode_size.o $(SYSLIBS)
+
+ ext2_tdbtool: tdbtool.o
+ $(E) " LD $@"
+- $(Q) $(CC) -o ext2_tdbtool tdbtool.o tdb.o
++ $(Q) $(CC) -o ext2_tdbtool tdbtool.o tdb.o $(SYSLIBS)
+
+ extent_dbg.c: $(srcdir)/extent_dbg.ct
+ $(E) " MK_CMDS $<"
+@@ -372,11 +372,13 @@ tst_bitmaps_cmd.c: tst_bitmaps_cmd.ct
+ $(E) " MK_CMDS $@"
+ $(Q) DIR=$(srcdir) $(MK_CMDS) $(srcdir)/tst_bitmaps_cmd.ct
+
+-tst_bitmaps: tst_bitmaps.o tst_bitmaps_cmd.o $(STATIC_LIBEXT2FS) \
+- $(DEPSTATIC_LIBSS) $(DEPSTATIC_LIBCOM_ERR)
++tst_bitmaps: tst_bitmaps.o tst_bitmaps_cmd.o $(srcdir)/blkmap64_rb.c \
++ $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBSS) $(DEPSTATIC_LIBCOM_ERR)
+ $(E) " LD $@"
+- $(Q) $(CC) -o $@ tst_bitmaps.o tst_bitmaps_cmd.o $(ALL_CFLAGS) \
+- $(STATIC_LIBEXT2FS) $(STATIC_LIBSS) $(STATIC_LIBCOM_ERR)
++ $(Q) $(CC) -o $@ tst_bitmaps.o tst_bitmaps_cmd.o \
++ -DDEBUG_RB $(srcdir)/blkmap64_rb.c $(ALL_CFLAGS) \
++ $(STATIC_LIBEXT2FS) $(STATIC_LIBSS) $(STATIC_LIBCOM_ERR) \
++ $(SYSLIBS)
+
+ tst_extents: $(srcdir)/extent.c $(DEBUG_OBJS) $(DEPSTATIC_LIBSS) \
+ $(STATIC_LIBE2P) $(DEPLIBUUID) $(DEPLIBBLKID) $(DEPSTATIC_LIBCOM_ERR)
+@@ -384,27 +386,29 @@ tst_extents: $(srcdir)/extent.c $(DEBUG_
+ $(Q) $(CC) -o tst_extents $(srcdir)/extent.c \
+ $(ALL_CFLAGS) -DDEBUG $(DEBUG_OBJS) $(STATIC_LIBSS) \
+ $(STATIC_LIBE2P) $(STATIC_LIBEXT2FS) $(LIBBLKID) $(LIBUUID) \
+- $(STATIC_LIBCOM_ERR) -I $(top_srcdir)/debugfs
++ $(STATIC_LIBCOM_ERR) $(SYSLIBS) -I $(top_srcdir)/debugfs
+
+ tst_inline: $(srcdir)/inline.c $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR)
+ $(E) " LD $@"
+ $(Q) $(CC) -o tst_inline $(srcdir)/inline.c $(ALL_CFLAGS) -DDEBUG \
+- $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR)
++ $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR) $(SYSLIBS)
+
+ tst_csum: csum.c $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR) $(STATIC_LIBE2P) \
+ $(top_srcdir)/lib/e2p/e2p.h
+ $(E) " LD $@"
+ $(Q) $(CC) -o tst_csum $(srcdir)/csum.c -DDEBUG \
+ $(ALL_CFLAGS) $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR) \
+- $(STATIC_LIBE2P)
++ $(STATIC_LIBE2P) $(SYSLIBS)
+
+ tst_crc32c: $(srcdir)/crc32c.c $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR)
+ $(Q) $(CC) $(BUILD_LDFLAGS) $(ALL_CFLAGS) -o tst_crc32c $(srcdir)/crc32c.c \
+- -DUNITTEST $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR)
++ -DUNITTEST $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR) \
++ $(SYSLIBS)
+
+ mkjournal: mkjournal.c $(STATIC_LIBEXT2FS) $(DEPLIBCOM_ERR)
+ $(E) " LD $@"
+- $(Q) $(CC) -o mkjournal $(srcdir)/mkjournal.c -DDEBUG $(STATIC_LIBEXT2FS) $(LIBCOM_ERR) $(ALL_CFLAGS)
++ $(Q) $(CC) -o mkjournal $(srcdir)/mkjournal.c -DDEBUG \
++ $(STATIC_LIBEXT2FS) $(LIBCOM_ERR) $(ALL_CFLAGS) $(SYSLIBS)
+
+ check:: tst_bitops tst_badblocks tst_iscan tst_types tst_icount \
+ tst_super_size tst_types tst_inode_size tst_csum tst_crc32c tst_bitmaps \
+@@ -573,10 +577,11 @@ block.o: $(srcdir)/block.c $(top_builddi
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h
+ bmap.o: $(srcdir)/bmap.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(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_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
+ check_desc.o: $(srcdir)/check_desc.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+@@ -671,7 +676,7 @@ fileio.o: $(srcdir)/fileio.c $(top_build
+ $(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
++ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h $(srcdir)/ext2fsP.h
+ finddev.o: $(srcdir)/finddev.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/alloc.c
++++ e2fsprogs-1.42.9/lib/ext2fs/alloc.c
+@@ -27,48 +27,17 @@
+ #include "ext2fs.h"
+
+ /*
+- * Check for uninit block bitmaps and deal with them appropriately
++ * Clear the uninit block bitmap flag if necessary
+ */
+-static void check_block_uninit(ext2_filsys fs, ext2fs_block_bitmap map,
+- dgrp_t group)
++static void clear_block_uninit(ext2_filsys fs, dgrp_t group)
+ {
+- blk_t i;
+- blk64_t blk, super_blk, old_desc_blk, new_desc_blk;
+- int old_desc_blocks;
+-
+ if (!(EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) ||
+ !(ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT)))
+ return;
+
+- blk = ext2fs_group_first_block2(fs, group);
+-
+- ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
+- &old_desc_blk, &new_desc_blk, 0);
++ /* uninit block bitmaps are now initialized in read_bitmaps() */
+
+- if (fs->super->s_feature_incompat &
+- EXT2_FEATURE_INCOMPAT_META_BG)
+- old_desc_blocks = fs->super->s_first_meta_bg;
+- else
+- old_desc_blocks = fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
+-
+- for (i=0; i < fs->super->s_blocks_per_group; i++, blk++)
+- ext2fs_fast_unmark_block_bitmap2(map, blk);
+-
+- blk = ext2fs_group_first_block2(fs, group);
+- for (i=0; i < fs->super->s_blocks_per_group; i++, blk++) {
+- if ((blk == super_blk) ||
+- (old_desc_blk && old_desc_blocks &&
+- (blk >= old_desc_blk) &&
+- (blk < old_desc_blk + old_desc_blocks)) ||
+- (new_desc_blk && (blk == new_desc_blk)) ||
+- (blk == ext2fs_block_bitmap_loc(fs, group)) ||
+- (blk == ext2fs_inode_bitmap_loc(fs, group)) ||
+- (blk >= ext2fs_inode_table_loc(fs, group) &&
+- (blk < ext2fs_inode_table_loc(fs, group)
+- + fs->inode_blocks_per_group)))
+- ext2fs_fast_mark_block_bitmap2(map, blk);
+- }
+ ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
+ ext2fs_group_desc_csum_set(fs, group);
+ ext2fs_mark_super_dirty(fs);
+@@ -93,10 +62,11 @@ static void check_inode_uninit(ext2_fils
+ ext2fs_fast_unmark_inode_bitmap2(map, ino);
+
+ ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
++ /* Mimics what the kernel does */
++ ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
+ ext2fs_group_desc_csum_set(fs, group);
+ ext2fs_mark_ib_dirty(fs);
+ ext2fs_mark_super_dirty(fs);
+- check_block_uninit(fs, fs->block_map, group);
+ }
+
+ /*
+@@ -167,8 +137,8 @@ errcode_t ext2fs_new_inode(ext2_filsys f
+ errcode_t ext2fs_new_block2(ext2_filsys fs, blk64_t goal,
+ ext2fs_block_bitmap map, blk64_t *ret)
+ {
+- blk64_t i;
+- int c_ratio;
++ errcode_t retval;
++ blk64_t b;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+@@ -178,29 +148,21 @@ errcode_t ext2fs_new_block2(ext2_filsys
+ return EXT2_ET_NO_BLOCK_BITMAP;
+ if (!goal || (goal >= ext2fs_blocks_count(fs->super)))
+ goal = fs->super->s_first_data_block;
+- i = goal;
+- c_ratio = 1 << ext2fs_get_bitmap_granularity(map);
+- if (c_ratio > 1)
+- goal &= ~EXT2FS_CLUSTER_MASK(fs);
+- check_block_uninit(fs, map,
+- (i - fs->super->s_first_data_block) /
+- EXT2_BLOCKS_PER_GROUP(fs->super));
+- do {
+- if (((i - fs->super->s_first_data_block) %
+- EXT2_BLOCKS_PER_GROUP(fs->super)) == 0)
+- check_block_uninit(fs, map,
+- (i - fs->super->s_first_data_block) /
+- EXT2_BLOCKS_PER_GROUP(fs->super));
+-
+- if (!ext2fs_fast_test_block_bitmap2(map, i)) {
+- *ret = i;
+- return 0;
+- }
+- i = (i + c_ratio) & ~(c_ratio - 1);
+- if (i >= ext2fs_blocks_count(fs->super))
+- i = fs->super->s_first_data_block;
+- } while (i != goal);
+- return EXT2_ET_BLOCK_ALLOC_FAIL;
++ goal &= ~EXT2FS_CLUSTER_MASK(fs);
++
++ retval = ext2fs_find_first_zero_block_bitmap2(map,
++ goal, ext2fs_blocks_count(fs->super) - 1, &b);
++ if ((retval == ENOENT) && (goal != fs->super->s_first_data_block))
++ retval = ext2fs_find_first_zero_block_bitmap2(map,
++ fs->super->s_first_data_block, goal - 1, &b);
++ if (retval == ENOENT)
++ return EXT2_ET_BLOCK_ALLOC_FAIL;
++ if (retval)
++ return retval;
++
++ clear_block_uninit(fs, ext2fs_group_of_blk2(fs, b));
++ *ret = b;
++ return 0;
+ }
+
+ errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/alloc_sb.c
++++ e2fsprogs-1.42.9/lib/ext2fs/alloc_sb.c
+@@ -65,8 +65,6 @@ int ext2fs_reserve_super_and_bgd(ext2_fi
+ ext2fs_mark_block_bitmap2(bmap, 0);
+
+ if (old_desc_blk) {
+- if (fs->super->s_reserved_gdt_blocks && fs->block_map == bmap)
+- ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
+ num_blocks = old_desc_blocks;
+ if (old_desc_blk + num_blocks >= ext2fs_blocks_count(fs->super))
+ num_blocks = ext2fs_blocks_count(fs->super) -
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/alloc_stats.c
++++ e2fsprogs-1.42.9/lib/ext2fs/alloc_stats.c
+@@ -106,3 +106,44 @@ void ext2fs_set_block_alloc_stats_callba
+
+ fs->block_alloc_stats = func;
+ }
++
++void ext2fs_block_alloc_stats_range(ext2_filsys fs, blk64_t blk,
++ blk_t num, int inuse)
++{
++#ifndef OMIT_COM_ERR
++ if (blk + num > ext2fs_blocks_count(fs->super)) {
++ com_err("ext2fs_block_alloc_stats_range", 0,
++ "Illegal block range: %llu (%u) ",
++ (unsigned long long) blk, num);
++ return;
++ }
++#endif
++ if (inuse == 0)
++ return;
++ if (inuse > 0) {
++ ext2fs_mark_block_bitmap_range2(fs->block_map, blk, num);
++ inuse = 1;
++ } else {
++ ext2fs_unmark_block_bitmap_range2(fs->block_map, blk, num);
++ inuse = -1;
++ }
++ while (num) {
++ int group = ext2fs_group_of_blk2(fs, blk);
++ blk64_t last_blk = ext2fs_group_last_block2(fs, group);
++ blk_t n = num;
++
++ if (blk + num > last_blk)
++ n = last_blk - blk + 1;
++
++ ext2fs_bg_free_blocks_count_set(fs, group,
++ ext2fs_bg_free_blocks_count(fs, group) -
++ inuse*n/EXT2FS_CLUSTER_RATIO(fs));
++ ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
++ ext2fs_group_desc_csum_set(fs, group);
++ ext2fs_free_blocks_count_add(fs->super, -inuse * n);
++ blk += n;
++ num -= n;
++ }
++ ext2fs_mark_super_dirty(fs);
++ ext2fs_mark_bb_dirty(fs);
++}
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/alloc_tables.c
++++ e2fsprogs-1.42.9/lib/ext2fs/alloc_tables.c
+@@ -83,9 +83,8 @@ static blk64_t flexbg_offset(ext2_filsys
+ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
+ ext2fs_block_bitmap bmap)
+ {
+- unsigned int j;
+ errcode_t retval;
+- blk64_t group_blk, start_blk, last_blk, new_blk, blk;
++ blk64_t group_blk, start_blk, last_blk, new_blk;
+ dgrp_t last_grp = 0;
+ int rem_grps = 0, flexbg_size = 0;
+
+@@ -205,19 +204,12 @@ errcode_t ext2fs_allocate_group_table(ex
+ bmap, &new_blk);
+ if (retval)
+ return retval;
+- for (j=0, blk = new_blk;
+- j < fs->inode_blocks_per_group;
+- j++, blk++) {
+- ext2fs_mark_block_bitmap2(bmap, blk);
+- if (flexbg_size) {
+- dgrp_t gr = ext2fs_group_of_blk2(fs, blk);
+- ext2fs_bg_free_blocks_count_set(fs, gr, ext2fs_bg_free_blocks_count(fs, gr) - 1);
+- ext2fs_free_blocks_count_add(fs->super, -1);
+- ext2fs_bg_flags_clear(fs, gr,
+- EXT2_BG_BLOCK_UNINIT);
+- ext2fs_group_desc_csum_set(fs, gr);
+- }
+- }
++ if (flexbg_size)
++ ext2fs_block_alloc_stats_range(fs, new_blk,
++ fs->inode_blocks_per_group, +1);
++ else
++ ext2fs_mark_block_bitmap_range2(fs->block_map,
++ new_blk, fs->inode_blocks_per_group);
+ ext2fs_inode_table_loc_set(fs, group, new_blk);
+ }
+ ext2fs_group_desc_csum_set(fs, group);
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/bitops.h
++++ e2fsprogs-1.42.9/lib/ext2fs/bitops.h
+@@ -157,6 +157,14 @@ extern errcode_t ext2fs_find_first_zero_
+ ext2_ino_t start,
+ ext2_ino_t end,
+ ext2_ino_t *out);
++extern errcode_t ext2fs_find_first_set_block_bitmap2(ext2fs_block_bitmap bitmap,
++ blk64_t start,
++ blk64_t end,
++ blk64_t *out);
++extern errcode_t ext2fs_find_first_set_inode_bitmap2(ext2fs_inode_bitmap bitmap,
++ ext2_ino_t start,
++ ext2_ino_t end,
++ ext2_ino_t *out);
+ extern blk64_t ext2fs_get_block_bitmap_start2(ext2fs_block_bitmap bitmap);
+ extern ext2_ino_t ext2fs_get_inode_bitmap_start2(ext2fs_inode_bitmap bitmap);
+ extern blk64_t ext2fs_get_block_bitmap_end2(ext2fs_block_bitmap bitmap);
+@@ -198,6 +206,9 @@ extern void ext2fs_unmark_block_bitmap_r
+ extern errcode_t ext2fs_find_first_zero_generic_bmap(ext2fs_generic_bitmap bitmap,
+ __u64 start, __u64 end,
+ __u64 *out);
++extern errcode_t ext2fs_find_first_set_generic_bmap(ext2fs_generic_bitmap bitmap,
++ __u64 start, __u64 end,
++ __u64 *out);
+
+ /*
+ * The inline routines themselves...
+@@ -602,6 +613,36 @@ _INLINE_ errcode_t ext2fs_find_first_zer
+ if (!rv)
+ *out = (ext2_ino_t) o;
+ return rv;
++}
++
++_INLINE_ errcode_t ext2fs_find_first_set_block_bitmap2(ext2fs_block_bitmap bitmap,
++ blk64_t start,
++ blk64_t end,
++ blk64_t *out)
++{
++ __u64 o;
++ errcode_t rv;
++
++ rv = ext2fs_find_first_set_generic_bmap((ext2fs_generic_bitmap) bitmap,
++ start, end, &o);
++ if (!rv)
++ *out = o;
++ return rv;
++}
++
++_INLINE_ errcode_t ext2fs_find_first_set_inode_bitmap2(ext2fs_inode_bitmap bitmap,
++ ext2_ino_t start,
++ ext2_ino_t end,
++ ext2_ino_t *out)
++{
++ __u64 o;
++ errcode_t rv;
++
++ rv = ext2fs_find_first_set_generic_bmap((ext2fs_generic_bitmap) bitmap,
++ start, end, &o);
++ if (!rv)
++ *out = (ext2_ino_t) o;
++ return rv;
+ }
+
+ _INLINE_ blk64_t ext2fs_get_block_bitmap_start2(ext2fs_block_bitmap bitmap)
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/blkmap64_ba.c
++++ e2fsprogs-1.42.9/lib/ext2fs/blkmap64_ba.c
+@@ -328,12 +328,6 @@ static errcode_t ba_find_first_zero(ext2
+ const unsigned char *pos;
+ unsigned long max_loop_count, i;
+
+- if (start < bitmap->start || end > bitmap->end || start > end)
+- return EINVAL;
+-
+- if (bitmap->cluster_bits)
+- return EINVAL;
+-
+ /* scan bits until we hit a byte boundary */
+ while ((bitpos & 0x7) != 0 && count > 0) {
+ if (!ext2fs_test_bit64(bitpos, bp->bitarray)) {
+@@ -397,6 +391,80 @@ static errcode_t ba_find_first_zero(ext2
+ return ENOENT;
+ }
+
++/* Find the first one bit between start and end, inclusive. */
++static errcode_t ba_find_first_set(ext2fs_generic_bitmap bitmap,
++ __u64 start, __u64 end, __u64 *out)
++{
++ ext2fs_ba_private bp = (ext2fs_ba_private)bitmap->private;
++ unsigned long bitpos = start - bitmap->start;
++ unsigned long count = end - start + 1;
++ int byte_found = 0; /* whether a != 0xff byte has been found */
++ const unsigned char *pos;
++ unsigned long max_loop_count, i;
++
++ /* scan bits until we hit a byte boundary */
++ while ((bitpos & 0x7) != 0 && count > 0) {
++ if (ext2fs_test_bit64(bitpos, bp->bitarray)) {
++ *out = bitpos + bitmap->start;
++ return 0;
++ }
++ bitpos++;
++ count--;
++ }
++
++ if (!count)
++ return ENOENT;
++
++ pos = ((unsigned char *)bp->bitarray) + (bitpos >> 3);
++ /* scan bytes until 8-byte (64-bit) aligned */
++ while (count >= 8 && (((unsigned long)pos) & 0x07)) {
++ if (*pos != 0) {
++ byte_found = 1;
++ break;
++ }
++ pos++;
++ count -= 8;
++ bitpos += 8;
++ }
++
++ if (!byte_found) {
++ max_loop_count = count >> 6; /* 8-byte blocks */
++ i = max_loop_count;
++ while (i) {
++ if (*((const __u64 *)pos) != 0)
++ break;
++ pos += 8;
++ i--;
++ }
++ count -= 64 * (max_loop_count - i);
++ bitpos += 64 * (max_loop_count - i);
++
++ max_loop_count = count >> 3;
++ i = max_loop_count;
++ while (i) {
++ if (*pos != 0) {
++ byte_found = 1;
++ break;
++ }
++ pos++;
++ i--;
++ }
++ count -= 8 * (max_loop_count - i);
++ bitpos += 8 * (max_loop_count - i);
++ }
++
++ /* Here either count < 8 or byte_found == 1. */
++ while (count-- > 0) {
++ if (ext2fs_test_bit64(bitpos, bp->bitarray)) {
++ *out = bitpos + bitmap->start;
++ return 0;
++ }
++ bitpos++;
++ }
++
++ return ENOENT;
++}
++
+ struct ext2_bitmap_ops ext2fs_blkmap64_bitarray = {
+ .type = EXT2FS_BMAP64_BITARRAY,
+ .new_bmap = ba_new_bmap,
+@@ -413,5 +481,6 @@ struct ext2_bitmap_ops ext2fs_blkmap64_b
+ .get_bmap_range = ba_get_bmap_range,
+ .clear_bmap = ba_clear_bmap,
+ .print_stats = ba_print_stats,
+- .find_first_zero = ba_find_first_zero
++ .find_first_zero = ba_find_first_zero,
++ .find_first_set = ba_find_first_set
+ };
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/blkmap64_rb.c
++++ e2fsprogs-1.42.9/lib/ext2fs/blkmap64_rb.c
+@@ -135,7 +135,7 @@ err_out:
+ }
+ #else
+ #define check_tree(root, msg) do {} while (0)
+-#define print_tree(root, msg) do {} while (0)
++#define print_tree(root) do {} while (0)
+ #endif
+
+ static void rb_get_new_extent(struct bmap_rb_extent **ext, __u64 start,
+@@ -569,11 +569,14 @@ static int rb_remove_extent(__u64 start,
+ static int rb_mark_bmap(ext2fs_generic_bitmap bitmap, __u64 arg)
+ {
+ struct ext2fs_rb_private *bp;
++ int retval;
+
+ bp = (struct ext2fs_rb_private *) bitmap->private;
+ arg -= bitmap->start;
+
+- return rb_insert_extent(arg, 1, bp);
++ retval = rb_insert_extent(arg, 1, bp);
++ check_tree(&bp->root, __func__);
++ return retval;
+ }
+
+ static int rb_unmark_bmap(ext2fs_generic_bitmap bitmap, __u64 arg)
+@@ -610,6 +613,7 @@ static void rb_mark_bmap_extent(ext2fs_g
+ arg -= bitmap->start;
+
+ rb_insert_extent(arg, num, bp);
++ check_tree(&bp->root, __func__);
+ }
+
+ static void rb_unmark_bmap_extent(ext2fs_generic_bitmap bitmap, __u64 arg,
+@@ -714,11 +718,14 @@ static errcode_t rb_set_bmap_range(ext2f
+
+ rb_insert_extent(start + first_set - bitmap->start,
+ i - first_set, bp);
++ check_tree(&bp->root, __func__);
+ first_set = -1;
+ }
+- if (first_set != -1)
++ if (first_set != -1) {
+ rb_insert_extent(start + first_set - bitmap->start,
+ num - first_set, bp);
++ check_tree(&bp->root, __func__);
++ }
+
+ return 0;
+ }
+@@ -799,6 +806,94 @@ static void rb_clear_bmap(ext2fs_generic
+ bp->rcursor = NULL;
+ bp->rcursor_next = NULL;
+ bp->wcursor = NULL;
++ check_tree(&bp->root, __func__);
++}
++
++static errcode_t rb_find_first_zero(ext2fs_generic_bitmap bitmap,
++ __u64 start, __u64 end, __u64 *out)
++{
++ struct rb_node *parent = NULL, **n;
++ struct rb_node *node, *next;
++ struct ext2fs_rb_private *bp;
++ struct bmap_rb_extent *ext;
++ int retval = 1;
++
++ bp = (struct ext2fs_rb_private *) bitmap->private;
++ n = &bp->root.rb_node;
++ start -= bitmap->start;
++ end -= bitmap->start;
++
++ if (start > end)
++ return EINVAL;
++
++ if (EXT2FS_RB_EMPTY_ROOT(&bp->root))
++ return ENOENT;
++
++ while (*n) {
++ parent = *n;
++ ext = node_to_extent(parent);
++ if (start < ext->start) {
++ n = &(*n)->rb_left;
++ } else if (start >= (ext->start + ext->count)) {
++ n = &(*n)->rb_right;
++ } else if (ext->start + ext->count <= end) {
++ *out = ext->start + ext->count + bitmap->start;
++ return 0;
++ } else
++ return ENOENT;
++ }
++
++ *out = start + bitmap->start;
++ return 0;
++}
++
++static errcode_t rb_find_first_set(ext2fs_generic_bitmap bitmap,
++ __u64 start, __u64 end, __u64 *out)
++{
++ struct rb_node *parent = NULL, **n;
++ struct rb_node *node, *next;
++ struct ext2fs_rb_private *bp;
++ struct bmap_rb_extent *ext;
++ int retval = 1;
++
++ bp = (struct ext2fs_rb_private *) bitmap->private;
++ n = &bp->root.rb_node;
++ start -= bitmap->start;
++ end -= bitmap->start;
++
++ if (start > end)
++ return EINVAL;
++
++ if (EXT2FS_RB_EMPTY_ROOT(&bp->root))
++ return ENOENT;
++
++ while (*n) {
++ parent = *n;
++ ext = node_to_extent(parent);
++ if (start < ext->start) {
++ n = &(*n)->rb_left;
++ } else if (start >= (ext->start + ext->count)) {
++ n = &(*n)->rb_right;
++ } else {
++ /* The start bit is set */
++ *out = start + bitmap->start;
++ return 0;
++ }
++ }
++
++ node = parent;
++ ext = node_to_extent(node);
++ if (ext->start < start) {
++ node = ext2fs_rb_next(node);
++ if (node == NULL)
++ return ENOENT;
++ ext = node_to_extent(node);
++ }
++ if (ext->start <= end) {
++ *out = ext->start + bitmap->start;
++ return 0;
++ }
++ return ENOENT;
+ }
+
+ #ifdef BMAP_STATS
+@@ -819,7 +914,6 @@ static void rb_print_stats(ext2fs_generi
+
+ bp = (struct ext2fs_rb_private *) bitmap->private;
+
+- node = ext2fs_rb_first(&bp->root);
+ for (node = ext2fs_rb_first(&bp->root); node != NULL;
+ node = ext2fs_rb_next(node)) {
+ ext = node_to_extent(node);
+@@ -883,4 +977,6 @@ struct ext2_bitmap_ops ext2fs_blkmap64_r
+ .get_bmap_range = rb_get_bmap_range,
+ .clear_bmap = rb_clear_bmap,
+ .print_stats = rb_print_stats,
++ .find_first_zero = rb_find_first_zero,
++ .find_first_set = rb_find_first_set,
+ };
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/bmap64.h
++++ e2fsprogs-1.42.9/lib/ext2fs/bmap64.h
+@@ -94,6 +94,10 @@ struct ext2_bitmap_ops {
+ * May be NULL, in which case a generic function is used. */
+ errcode_t (*find_first_zero)(ext2fs_generic_bitmap bitmap,
+ __u64 start, __u64 end, __u64 *out);
++ /* Find the first set bit between start and end, inclusive.
++ * May be NULL, in which case a generic function is used. */
++ errcode_t (*find_first_set)(ext2fs_generic_bitmap bitmap,
++ __u64 start, __u64 end, __u64 *out);
+ };
+
+ extern struct ext2_bitmap_ops ext2fs_blkmap64_bitarray;
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/closefs.c
++++ e2fsprogs-1.42.9/lib/ext2fs/closefs.c
+@@ -35,8 +35,16 @@ static int test_root(unsigned int a, uns
+
+ int ext2fs_bg_has_super(ext2_filsys fs, dgrp_t group)
+ {
+- if (!(fs->super->s_feature_ro_compat &
+- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) || group <= 1)
++ if (group == 0)
++ return 1;
++ if (fs->super->s_feature_compat & EXT4_FEATURE_COMPAT_SPARSE_SUPER2) {
++ if (group == fs->super->s_backup_bgs[0] ||
++ group == fs->super->s_backup_bgs[1])
++ return 1;
++ return 0;
++ }
++ if ((group <= 1) || !(fs->super->s_feature_ro_compat &
++ EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
+ return 1;
+ if (!(group & 1))
+ return 0;
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/csum.c
++++ e2fsprogs-1.42.9/lib/ext2fs/csum.c
+@@ -36,7 +36,7 @@ __u16 ext2fs_group_desc_csum(ext2_filsys
+ group);
+ size_t size = EXT2_DESC_SIZE(fs->super);
+ size_t offset;
+- __u16 crc;
++ __u16 crc = 0;
+
+ if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
+ size_t offset = offsetof(struct ext2_group_desc, bg_checksum);
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/ext2_fs.h
++++ e2fsprogs-1.42.9/lib/ext2fs/ext2_fs.h
+@@ -645,7 +645,8 @@ struct ext2_super_block {
+ __u32 s_usr_quota_inum; /* inode number of user quota file */
+ __u32 s_grp_quota_inum; /* inode number of group quota file */
+ __u32 s_overhead_blocks; /* overhead blocks/clusters in fs */
+- __u32 s_reserved[108]; /* Padding to the end of the block */
++ __u32 s_backup_bgs[2]; /* If sparse_super2 enabled */
++ __u32 s_reserved[106]; /* Padding to the end of the block */
+ __u32 s_checksum; /* crc32c(superblock) */
+ };
+
+@@ -696,6 +697,7 @@ struct ext2_super_block {
+ #define EXT2_FEATURE_COMPAT_LAZY_BG 0x0040
+ /* #define EXT2_FEATURE_COMPAT_EXCLUDE_INODE 0x0080 not used, legacy */
+ #define EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP 0x0100
++#define EXT4_FEATURE_COMPAT_SPARSE_SUPER2 0x0200
+
+
+ #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/ext2fs.h
++++ e2fsprogs-1.42.9/lib/ext2fs/ext2fs.h
+@@ -550,7 +550,8 @@ typedef struct ext2_icount *ext2_icount_
+ EXT3_FEATURE_COMPAT_HAS_JOURNAL|\
+ EXT2_FEATURE_COMPAT_RESIZE_INODE|\
+ EXT2_FEATURE_COMPAT_DIR_INDEX|\
+- EXT2_FEATURE_COMPAT_EXT_ATTR)
++ EXT2_FEATURE_COMPAT_EXT_ATTR|\
++ EXT4_FEATURE_COMPAT_SPARSE_SUPER2)
+
+ /* This #ifdef is temporary until compression is fully supported */
+ #ifdef ENABLE_COMPRESSION
+@@ -683,6 +684,8 @@ void ext2fs_inode_alloc_stats2(ext2_fils
+ int inuse, int isdir);
+ void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse);
+ void ext2fs_block_alloc_stats2(ext2_filsys fs, blk64_t blk, int inuse);
++void ext2fs_block_alloc_stats_range(ext2_filsys fs, blk64_t blk,
++ blk_t num, int inuse);
+
+ /* alloc_tables.c */
+ extern errcode_t ext2fs_allocate_tables(ext2_filsys fs);
+@@ -1177,6 +1180,9 @@ extern errcode_t ext2fs_set_generic_bitm
+ extern errcode_t ext2fs_find_first_zero_generic_bitmap(ext2fs_generic_bitmap bitmap,
+ __u32 start, __u32 end,
+ __u32 *out);
++extern errcode_t ext2fs_find_first_set_generic_bitmap(ext2fs_generic_bitmap bitmap,
++ __u32 start, __u32 end,
++ __u32 *out);
+
+ /* gen_bitmap64.c */
+
+@@ -1365,6 +1371,8 @@ extern errcode_t ext2fs_add_journal_devi
+ ext2_filsys journal_dev);
+ extern errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t num_blocks,
+ int flags);
++extern errcode_t ext2fs_add_journal_inode2(ext2_filsys fs, blk_t num_blocks,
++ blk64_t goal, int flags);
+ extern int ext2fs_default_journal_size(__u64 num_blocks);
+
+ /* openfs.c */
+@@ -1375,6 +1383,11 @@ extern errcode_t ext2fs_open2(const char
+ int flags, int superblock,
+ unsigned int block_size, io_manager manager,
+ ext2_filsys *ret_fs);
++/*
++ * The dgrp_t argument to these two functions is not actually a group number
++ * but a block number offset within a group table! Convert with the formula
++ * (group_number / groups_per_block).
++ */
+ extern blk64_t ext2fs_descriptor_block_loc2(ext2_filsys fs,
+ blk64_t group_block, dgrp_t i);
+ extern blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block,
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/extent.c
++++ e2fsprogs-1.42.9/lib/ext2fs/extent.c
+@@ -1092,8 +1092,10 @@ errcode_t ext2fs_extent_insert(ext2_exte
+ ix++;
+ path->left--;
+ }
+- } else
++ } else {
+ ix = EXT_FIRST_INDEX(eh);
++ path->left = -1;
++ }
+
+ path->curr = ix;
+
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/gen_bitmap.c
++++ e2fsprogs-1.42.9/lib/ext2fs/gen_bitmap.c
+@@ -527,6 +527,28 @@ errcode_t ext2fs_find_first_zero_generic
+ return ENOENT;
+ }
+
++errcode_t ext2fs_find_first_set_generic_bitmap(ext2fs_generic_bitmap bitmap,
++ __u32 start, __u32 end,
++ __u32 *out)
++{
++ blk_t b;
++
++ if (start < bitmap->start || end > bitmap->end || start > end) {
++ ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start);
++ return EINVAL;
++ }
++
++ while (start <= end) {
++ b = ext2fs_test_bit(start - bitmap->start, bitmap->bitmap);
++ if (b) {
++ *out = start;
++ return 0;
++ }
++ start++;
++ }
++
++ return ENOENT;
++}
+
+ int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
+ blk_t block, int num)
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/gen_bitmap64.c
++++ e2fsprogs-1.42.9/lib/ext2fs/gen_bitmap64.c
+@@ -801,17 +801,14 @@ errcode_t ext2fs_find_first_zero_generic
+ __u64 start, __u64 end, __u64 *out)
+ {
+ int b;
++ __u64 cstart, cend, cout;
++ errcode_t retval;
+
+ if (!bitmap)
+ return EINVAL;
+
+- if (EXT2FS_IS_64_BITMAP(bitmap) && bitmap->bitmap_ops->find_first_zero)
+- return bitmap->bitmap_ops->find_first_zero(bitmap, start,
+- end, out);
+-
+ if (EXT2FS_IS_32_BITMAP(bitmap)) {
+ blk_t blk = 0;
+- errcode_t retval;
+
+ if (((start) & ~0xffffffffULL) ||
+ ((end) & ~0xffffffffULL)) {
+@@ -829,22 +826,83 @@ errcode_t ext2fs_find_first_zero_generic
+ if (!EXT2FS_IS_64_BITMAP(bitmap))
+ return EINVAL;
+
+- start >>= bitmap->cluster_bits;
+- end >>= bitmap->cluster_bits;
++ cstart = start >> bitmap->cluster_bits;
++ cend = end >> bitmap->cluster_bits;
+
+- if (start < bitmap->start || end > bitmap->end || start > end) {
++ if (cstart < bitmap->start || cend > bitmap->end || start > end) {
+ warn_bitmap(bitmap, EXT2FS_TEST_ERROR, start);
+ return EINVAL;
+ }
+
+- while (start <= end) {
+- b = bitmap->bitmap_ops->test_bmap(bitmap, start);
+- if (!b) {
+- *out = start << bitmap->cluster_bits;
+- return 0;
++ if (bitmap->bitmap_ops->find_first_zero) {
++ retval = bitmap->bitmap_ops->find_first_zero(bitmap, cstart,
++ cend, &cout);
++ if (retval)
++ return retval;
++ found:
++ cout <<= bitmap->cluster_bits;
++ *out = (cout >= start) ? cout : start;
++ return 0;
++ }
++
++ for (cout = cstart; cout <= cend; cout++)
++ if (!bitmap->bitmap_ops->test_bmap(bitmap, cout))
++ goto found;
++
++ return ENOENT;
++}
++
++errcode_t ext2fs_find_first_set_generic_bmap(ext2fs_generic_bitmap bitmap,
++ __u64 start, __u64 end, __u64 *out)
++{
++ int b;
++ __u64 cstart, cend, cout;
++ errcode_t retval;
++
++ if (!bitmap)
++ return EINVAL;
++
++ if (EXT2FS_IS_32_BITMAP(bitmap)) {
++ blk_t blk = 0;
++
++ if (((start) & ~0xffffffffULL) ||
++ ((end) & ~0xffffffffULL)) {
++ ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start);
++ return EINVAL;
+ }
+- start++;
++
++ retval = ext2fs_find_first_set_generic_bitmap(bitmap, start,
++ end, &blk);
++ if (retval == 0)
++ *out = blk;
++ return retval;
+ }
+
++ if (!EXT2FS_IS_64_BITMAP(bitmap))
++ return EINVAL;
++
++ cstart = start >> bitmap->cluster_bits;
++ cend = end >> bitmap->cluster_bits;
++
++ if (cstart < bitmap->start || cend > bitmap->end || start > end) {
++ warn_bitmap(bitmap, EXT2FS_TEST_ERROR, start);
++ return EINVAL;
++ }
++
++ if (bitmap->bitmap_ops->find_first_set) {
++ retval = bitmap->bitmap_ops->find_first_set(bitmap, cstart,
++ cend, &cout);
++ if (retval)
++ return retval;
++ found:
++ cout <<= bitmap->cluster_bits;
++ *out = (cout >= start) ? cout : start;
++ return 0;
++ }
++
++ for (cout = cstart; cout <= cend; cout++)
++ if (bitmap->bitmap_ops->test_bmap(bitmap, cout))
++ goto found;
++
+ return ENOENT;
+ }
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/icount.c
++++ e2fsprogs-1.42.9/lib/ext2fs/icount.c
+@@ -181,6 +181,7 @@ errcode_t ext2fs_create_icount_tdb(ext2_
+ errcode_t retval;
+ char *fn, uuid[40];
+ ext2_ino_t num_inodes;
++ mode_t save_umask;
+ int fd;
+
+ retval = alloc_icount(fs, flags, &icount);
+@@ -192,10 +193,14 @@ errcode_t ext2fs_create_icount_tdb(ext2_
+ goto errout;
+ uuid_unparse(fs->super->s_uuid, uuid);
+ sprintf(fn, "%s/%s-icount-XXXXXX", tdb_dir, uuid);
++ icount->tdb_fn = fn;
++ save_umask = umask(077);
+ fd = mkstemp(fn);
+- if (fd < 0)
+- return fd;
+-
++ if (fd < 0) {
++ retval = errno;
++ goto errout;
++ }
++ umask(save_umask);
+ /*
+ * This is an overestimate of the size that we will need; the
+ * ideal value is the number of used inodes with a count
+@@ -206,18 +211,15 @@ errcode_t ext2fs_create_icount_tdb(ext2_
+ */
+ num_inodes = fs->super->s_inodes_count - fs->super->s_free_inodes_count;
+
+- icount->tdb_fn = fn;
+ icount->tdb = tdb_open(fn, num_inodes, TDB_NOLOCK | TDB_NOSYNC,
+ O_RDWR | O_CREAT | O_TRUNC, 0600);
+- if (icount->tdb) {
+- close(fd);
+- *ret = icount;
+- return 0;
+- }
+-
+- retval = errno;
+ close(fd);
+-
++ if (icount->tdb == NULL) {
++ retval = errno;
++ goto errout;
++ }
++ *ret = icount;
++ return 0;
+ errout:
+ ext2fs_free_icount(icount);
+ return(retval);
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/initialize.c
++++ e2fsprogs-1.42.9/lib/ext2fs/initialize.c
+@@ -173,6 +173,8 @@ errcode_t ext2fs_initialize(const char *
+ set_field(s_raid_stripe_width, 0); /* default stripe width: 0 */
+ set_field(s_log_groups_per_flex, 0);
+ set_field(s_flags, 0);
++ assign_field(s_backup_bgs[0]);
++ assign_field(s_backup_bgs[1]);
+ if (super->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) {
+ retval = EXT2_ET_UNSUPP_FEATURE;
+ goto cleanup;
+@@ -422,6 +424,21 @@ ipg_retry:
+ * count.
+ */
+
++ /* Set up the locations of the backup superblocks */
++ if (super->s_feature_compat & EXT4_FEATURE_COMPAT_SPARSE_SUPER2) {
++ if (super->s_backup_bgs[0] >= fs->group_desc_count)
++ super->s_backup_bgs[0] = fs->group_desc_count - 1;
++ if (super->s_backup_bgs[1] >= fs->group_desc_count)
++ super->s_backup_bgs[1] = fs->group_desc_count - 1;
++ if (super->s_backup_bgs[0] == super->s_backup_bgs[1])
++ super->s_backup_bgs[1] = 0;
++ if (super->s_backup_bgs[0] > super->s_backup_bgs[1]) {
++ __u32 t = super->s_backup_bgs[0];
++ super->s_backup_bgs[0] = super->s_backup_bgs[1];
++ super->s_backup_bgs[1] = t;
++ }
++ }
++
+ retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
+ if (retval)
+ goto cleanup;
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/mkjournal.c
++++ e2fsprogs-1.42.9/lib/ext2fs/mkjournal.c
+@@ -295,13 +295,43 @@ static int mkjournal_proc(ext2_filsys fs
+ }
+
+ /*
++ * Calculate the initial goal block to be roughly at the middle of the
++ * filesystem. Pick a group that has the largest number of free
++ * blocks.
++ */
++static blk64_t get_midpoint_journal_block(ext2_filsys fs)
++{
++ dgrp_t group, start, end, i, log_flex;
++
++ group = ext2fs_group_of_blk2(fs, (ext2fs_blocks_count(fs->super) -
++ fs->super->s_first_data_block) / 2);
++ log_flex = 1 << fs->super->s_log_groups_per_flex;
++ if (fs->super->s_log_groups_per_flex && (group > log_flex)) {
++ group = group & ~(log_flex - 1);
++ while ((group < fs->group_desc_count) &&
++ ext2fs_bg_free_blocks_count(fs, group) == 0)
++ group++;
++ if (group == fs->group_desc_count)
++ group = 0;
++ start = group;
++ } else
++ start = (group > 0) ? group-1 : group;
++ end = ((group+1) < fs->group_desc_count) ? group+1 : group;
++ group = start;
++ for (i = start + 1; i <= end; i++)
++ if (ext2fs_bg_free_blocks_count(fs, i) >
++ ext2fs_bg_free_blocks_count(fs, group))
++ group = i;
++ return ext2fs_group_first_block2(fs, group);
++}
++
++/*
+ * This function creates a journal using direct I/O routines.
+ */
+ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
+- blk_t num_blocks, int flags)
++ blk_t num_blocks, blk64_t goal, int flags)
+ {
+ char *buf;
+- dgrp_t group, start, end, i, log_flex;
+ errcode_t retval;
+ struct ext2_inode inode;
+ unsigned long long inode_size;
+@@ -328,6 +358,7 @@ static errcode_t write_journal_inode(ext
+ es.err = 0;
+ es.flags = flags;
+ es.zero_count = 0;
++ es.goal = (goal != ~0ULL) ? goal : get_midpoint_journal_block(fs);
+
+ if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) {
+ inode.i_flags |= EXT4_EXTENTS_FL;
+@@ -335,32 +366,6 @@ static errcode_t write_journal_inode(ext
+ goto out2;
+ }
+
+- /*
+- * Set the initial goal block to be roughly at the middle of
+- * the filesystem. Pick a group that has the largest number
+- * of free blocks.
+- */
+- group = ext2fs_group_of_blk2(fs, (ext2fs_blocks_count(fs->super) -
+- fs->super->s_first_data_block) / 2);
+- log_flex = 1 << fs->super->s_log_groups_per_flex;
+- if (fs->super->s_log_groups_per_flex && (group > log_flex)) {
+- group = group & ~(log_flex - 1);
+- while ((group < fs->group_desc_count) &&
+- ext2fs_bg_free_blocks_count(fs, group) == 0)
+- group++;
+- if (group == fs->group_desc_count)
+- group = 0;
+- start = group;
+- } else
+- start = (group > 0) ? group-1 : group;
+- end = ((group+1) < fs->group_desc_count) ? group+1 : group;
+- group = start;
+- for (i=start+1; i <= end; i++)
+- if (ext2fs_bg_free_blocks_count(fs, i) >
+- ext2fs_bg_free_blocks_count(fs, group))
+- group = i;
+-
+- es.goal = ext2fs_group_first_block2(fs, group);
+ retval = ext2fs_block_iterate3(fs, journal_ino, BLOCK_FLAG_APPEND,
+ 0, mkjournal_proc, &es);
+ if (es.err) {
+@@ -491,7 +496,8 @@ errcode_t ext2fs_add_journal_device(ext2
+ * POSIX routines if the filesystem is mounted, or using direct I/O
+ * functions if it is not.
+ */
+-errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t num_blocks, int flags)
++errcode_t ext2fs_add_journal_inode2(ext2_filsys fs, blk_t num_blocks,
++ blk64_t goal, int flags)
+ {
+ errcode_t retval;
+ ext2_ino_t journal_ino;
+@@ -582,7 +588,7 @@ errcode_t ext2fs_add_journal_inode(ext2_
+ }
+ journal_ino = EXT2_JOURNAL_INO;
+ if ((retval = write_journal_inode(fs, journal_ino,
+- num_blocks, flags)))
++ num_blocks, goal, flags)))
+ return retval;
+ }
+
+@@ -600,6 +606,12 @@ errout:
+ return retval;
+ }
+
++errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t num_blocks, int flags)
++{
++ return ext2fs_add_journal_inode2(fs, num_blocks, ~0ULL, flags);
++}
++
++
+ #ifdef DEBUG
+ main(int argc, char **argv)
+ {
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/openfs.c
++++ e2fsprogs-1.42.9/lib/ext2fs/openfs.c
+@@ -37,17 +37,24 @@ blk64_t ext2fs_descriptor_block_loc2(ext
+ dgrp_t i)
+ {
+ int bg;
+- int has_super = 0;
++ int has_super = 0, group_zero_adjust = 0;
+ blk64_t ret_blk;
+
++ /*
++ * On a bigalloc FS with 1K blocks, block 0 is reserved for non-ext4
++ * stuff, so adjust for that if we're being asked for group 0.
++ */
++ if (i == 0 && fs->blocksize == 1024 && EXT2FS_CLUSTER_RATIO(fs) > 1)
++ group_zero_adjust = 1;
++
+ if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
+ (i < fs->super->s_first_meta_bg))
+- return (group_block + i + 1);
++ return group_block + i + 1 + group_zero_adjust;
+
+ bg = EXT2_DESC_PER_BLOCK(fs->super) * i;
+ if (ext2fs_bg_has_super(fs, bg))
+ has_super = 1;
+- ret_blk = ext2fs_group_first_block2(fs, bg) + has_super;
++ ret_blk = ext2fs_group_first_block2(fs, bg);
+ /*
+ * If group_block is not the normal value, we're trying to use
+ * the backup group descriptors and superblock --- so use the
+@@ -57,10 +64,21 @@ blk64_t ext2fs_descriptor_block_loc2(ext
+ * have the infrastructure in place to do that.
+ */
+ if (group_block != fs->super->s_first_data_block &&
+- ((ret_blk + fs->super->s_blocks_per_group) <
+- ext2fs_blocks_count(fs->super)))
++ ((ret_blk + has_super + fs->super->s_blocks_per_group) <
++ ext2fs_blocks_count(fs->super))) {
+ ret_blk += fs->super->s_blocks_per_group;
+- return ret_blk;
++
++ /*
++ * If we're going to jump forward a block group, make sure
++ * that we adjust has_super to account for the next group's
++ * backup superblock (or lack thereof).
++ */
++ if (ext2fs_bg_has_super(fs, bg + 1))
++ has_super = 1;
++ else
++ has_super = 0;
++ }
++ return ret_blk + has_super + group_zero_adjust;
+ }
+
+ blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i)
+@@ -102,6 +120,7 @@ errcode_t ext2fs_open2(const char *name,
+ unsigned int blocks_per_group, io_flags;
+ blk64_t group_block, blk;
+ char *dest, *cp;
++ int group_zero_adjust = 0;
+ #ifdef WORDS_BIGENDIAN
+ unsigned int groups_per_block;
+ struct ext2_group_desc *gdp;
+@@ -342,8 +361,19 @@ errcode_t ext2fs_open2(const char *name,
+ goto cleanup;
+ if (!group_block)
+ group_block = fs->super->s_first_data_block;
++ /*
++ * On a FS with a 1K blocksize, block 0 is reserved for bootloaders
++ * so we must increment block numbers to any group 0 items.
++ *
++ * However, we cannot touch group_block directly because in the meta_bg
++ * case, the ext2fs_descriptor_block_loc2() function will interpret
++ * group_block != s_first_data_block to mean that we want to access the
++ * backup group descriptors. This is not what we want if the caller
++ * set superblock == 0 (i.e. auto-detect the superblock), which is
++ * what's going on here.
++ */
+ if (group_block == 0 && fs->blocksize == 1024)
+- group_block = 1; /* Deal with 1024 blocksize && bigalloc */
++ group_zero_adjust = 1;
+ dest = (char *) fs->group_desc;
+ #ifdef WORDS_BIGENDIAN
+ groups_per_block = EXT2_DESC_PER_BLOCK(fs->super);
+@@ -353,7 +383,8 @@ errcode_t ext2fs_open2(const char *name,
+ else
+ first_meta_bg = fs->desc_blocks;
+ if (first_meta_bg) {
+- retval = io_channel_read_blk(fs->io, group_block+1,
++ retval = io_channel_read_blk(fs->io, group_block +
++ group_zero_adjust + 1,
+ first_meta_bg, dest);
+ if (retval)
+ goto cleanup;
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/qcow2.c
++++ e2fsprogs-1.42.9/lib/ext2fs/qcow2.c
+@@ -235,8 +235,10 @@ int qcow2_write_raw_image(int qcow2_fd,
+ }
+
+ /* Resize the output image to the filesystem size */
+- if (ext2fs_llseek(raw_fd, img.image_size - 1, SEEK_SET) < 0)
+- return errno;
++ if (ext2fs_llseek(raw_fd, img.image_size - 1, SEEK_SET) < 0) {
++ ret = errno;
++ goto out;
++ }
+
+ ((char *)copy_buf)[0] = 0;
+ size = write(raw_fd, copy_buf, 1);
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/res_gdt.c
++++ e2fsprogs-1.42.9/lib/ext2fs/res_gdt.c
+@@ -31,6 +31,19 @@ static unsigned int list_backups(ext2_fi
+ int mult = 3;
+ unsigned int ret;
+
++ if (fs->super->s_feature_compat & EXT4_FEATURE_COMPAT_SPARSE_SUPER2) {
++ if (*min == 1) {
++ *min += 1;
++ if (fs->super->s_backup_bgs[0])
++ return fs->super->s_backup_bgs[0];
++ }
++ if (*min == 2) {
++ *min += 1;
++ if (fs->super->s_backup_bgs[1])
++ return fs->super->s_backup_bgs[1];
++ }
++ return fs->group_desc_count;
++ }
+ if (!(fs->super->s_feature_ro_compat &
+ EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
+ ret = *min;
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/rw_bitmaps.c
++++ e2fsprogs-1.42.9/lib/ext2fs/rw_bitmaps.c
+@@ -145,6 +145,43 @@ errout:
+ return retval;
+ }
+
++static errcode_t mark_uninit_bg_group_blocks(ext2_filsys fs)
++{
++ dgrp_t i;
++ blk64_t blk;
++ ext2fs_block_bitmap bmap = fs->block_map;
++
++ for (i = 0; i < fs->group_desc_count; i++) {
++ if (!ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT))
++ continue;
++
++ ext2fs_reserve_super_and_bgd(fs, i, bmap);
++
++ /*
++ * Mark the blocks used for the inode table
++ */
++ blk = ext2fs_inode_table_loc(fs, i);
++ if (blk)
++ ext2fs_mark_block_bitmap_range2(bmap, blk,
++ fs->inode_blocks_per_group);
++
++ /*
++ * Mark block used for the block bitmap
++ */
++ blk = ext2fs_block_bitmap_loc(fs, i);
++ if (blk)
++ ext2fs_mark_block_bitmap2(bmap, blk);
++
++ /*
++ * Mark block used for the inode bitmap
++ */
++ blk = ext2fs_inode_bitmap_loc(fs, i);
++ if (blk)
++ ext2fs_mark_block_bitmap2(bmap, blk);
++ }
++ return 0;
++}
++
+ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
+ {
+ dgrp_t i;
+@@ -292,6 +329,14 @@ static errcode_t read_bitmaps(ext2_filsy
+ ino_itr += inode_nbytes << 3;
+ }
+ }
++
++ /* Mark group blocks for any BLOCK_UNINIT groups */
++ if (do_block) {
++ retval = mark_uninit_bg_group_blocks(fs);
++ if (retval)
++ goto cleanup;
++ }
++
+ success_cleanup:
+ if (inode_bitmap)
+ ext2fs_free_mem(&inode_bitmap);
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/swapfs.c
++++ e2fsprogs-1.42.9/lib/ext2fs/swapfs.c
+@@ -99,6 +99,8 @@ void ext2fs_swap_super(struct ext2_super
+ }
+ for (; i < 17; i++)
+ sb->s_jnl_blocks[i] = ext2fs_swab32(sb->s_jnl_blocks[i]);
++ sb->s_backup_bgs[0] = ext2fs_swab32(sb->s_backup_bgs[0]);
++ sb->s_backup_bgs[1] = ext2fs_swab32(sb->s_backup_bgs[1]);
+ }
+
+ void ext2fs_swap_group_desc2(ext2_filsys fs, struct ext2_group_desc *gdp)
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/tst_bitmaps.c
++++ e2fsprogs-1.42.9/lib/ext2fs/tst_bitmaps.c
+@@ -436,6 +436,39 @@ void do_ffzb(int argc, char *argv[])
+ printf("First unmarked block is %llu\n", out);
+ }
+
++void do_ffsb(int argc, char *argv[])
++{
++ unsigned int start, end;
++ int err;
++ errcode_t retval;
++ blk64_t out;
++
++ if (check_fs_open(argv[0]))
++ return;
++
++ if (argc != 3 && argc != 3) {
++ com_err(argv[0], 0, "Usage: ffsb <start> <end>");
++ return;
++ }
++
++ start = parse_ulong(argv[1], argv[0], "start", &err);
++ if (err)
++ return;
++
++ end = parse_ulong(argv[2], argv[0], "end", &err);
++ if (err)
++ return;
++
++ retval = ext2fs_find_first_set_block_bitmap2(test_fs->block_map,
++ start, end, &out);
++ if (retval) {
++ printf("ext2fs_find_first_set_block_bitmap2() returned %s\n",
++ error_message(retval));
++ return;
++ }
++ printf("First marked block is %llu\n", out);
++}
++
+
+ void do_zerob(int argc, char *argv[])
+ {
+@@ -559,6 +592,38 @@ void do_ffzi(int argc, char *argv[])
+ printf("First unmarked inode is %u\n", out);
+ }
+
++void do_ffsi(int argc, char *argv[])
++{
++ unsigned int start, end;
++ int err;
++ errcode_t retval;
++ ext2_ino_t out;
++
++ if (check_fs_open(argv[0]))
++ return;
++
++ if (argc != 3 && argc != 3) {
++ com_err(argv[0], 0, "Usage: ffsi <start> <end>");
++ return;
++ }
++
++ start = parse_ulong(argv[1], argv[0], "start", &err);
++ if (err)
++ return;
++
++ end = parse_ulong(argv[2], argv[0], "end", &err);
++ if (err)
++ return;
++
++ retval = ext2fs_find_first_set_inode_bitmap2(test_fs->inode_map,
++ start, end, &out);
++ if (retval) {
++ printf("ext2fs_find_first_set_inode_bitmap2() returned %s\n",
++ error_message(retval));
++ return;
++ }
++ printf("First marked inode is %u\n", out);
++}
+
+ void do_zeroi(int argc, char *argv[])
+ {
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/tst_bitmaps_cmd.ct
++++ e2fsprogs-1.42.9/lib/ext2fs/tst_bitmaps_cmd.ct
+@@ -24,6 +24,9 @@ request do_testb, "Test block",
+ request do_ffzb, "Find first zero block",
+ find_first_zero_block, ffzb;
+
++request do_ffsb, "Find first set block",
++ find_first_set_block, ffsb;
++
+ request do_zerob, "Clear block bitmap",
+ clear_block_bitmap, zerob;
+
+@@ -39,6 +42,9 @@ request do_testi, "Test inode",
+ request do_ffzi, "Find first zero inode",
+ find_first_zero_inode, ffzi;
+
++request do_ffsi, "Find first set inode",
++ find_first_set_inode, ffsi;
++
+ request do_zeroi, "Clear inode bitmap",
+ clear_inode_bitmap, zeroi;
+
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/tst_bitmaps_cmds
++++ e2fsprogs-1.42.9/lib/ext2fs/tst_bitmaps_cmds
+@@ -19,8 +19,17 @@ dump_bb
+ ffzb 11 16
+ ffzb 12 16
+ ffzb 12 20
++ffsb 0 127
++ffsb 1 128
++ffsb 1 127
++ffsb 1 10
++ffsb 1 11
++ffsb 12 12
++ffsb 13 12
++ffsb 12 15
+ clearb 13
+ ffzb 12 20
++ffsb 13 18
+ setb 13
+ clearb 12 7
+ testb 12 7
+@@ -42,8 +51,15 @@ dump_ib
+ ffzi 1 6
+ ffzi 2 5
+ ffzi 2 6
++ffsi 0 31
++ffsi 1 33
++ffsi 1 32
++ffsi 2 32
++ffsi 6 32
+ cleari 4
+ ffzi 2 6
++ffsi 4 32
++ffsi 5 32
+ zeroi
+ testi 5
+ seti 5
+@@ -95,5 +111,38 @@ clearb 2
+ clearb 3
+ clearb 7
+ dump_bb
++ffsb 14 127
++ffsb 15 127
++ffsb 36 127
++ffsb 32 127
++ffsb 52 127
++ffsb 53 127
++ffsb 46 127
++ffsb 45 127
++ffsb 41 127
++ffsb 20 127
++ffsb 1 127
++ffsb 2 127
++ffsb 3 127
++ffsb 4 127
++ffsb 5 127
++ffsb 6 127
++ffsb 7 127
++ffsb 8 127
++ffzb 1 127
++ffzb 2 127
++ffzb 3 127
++ffzb 4 127
++ffzb 5 127
++ffzb 6 127
++ffzb 7 127
++ffzb 8 127
++ffzb 45 127
++ffzb 46 127
++ffzb 47 127
++ffzb 48 127
++ffzb 49 127
++ffzb 50 127
++ffzb 51 127
+ quit
+
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/tst_bitmaps_exp
++++ e2fsprogs-1.42.9/lib/ext2fs/tst_bitmaps_exp
+@@ -43,10 +43,28 @@ tst_bitmaps: ffzb 12 16
+ ext2fs_find_first_zero_block_bitmap2() returned No such file or directory
+ tst_bitmaps: ffzb 12 20
+ First unmarked block is 17
++tst_bitmaps: ffsb 0 127
++ext2fs_find_first_set_block_bitmap2() returned Invalid argument
++tst_bitmaps: ffsb 1 128
++ext2fs_find_first_set_block_bitmap2() returned Invalid argument
++tst_bitmaps: ffsb 1 127
++First marked block is 12
++tst_bitmaps: ffsb 1 10
++ext2fs_find_first_set_block_bitmap2() returned No such file or directory
++tst_bitmaps: ffsb 1 11
++ext2fs_find_first_set_block_bitmap2() returned No such file or directory
++tst_bitmaps: ffsb 12 12
++First marked block is 12
++tst_bitmaps: ffsb 13 12
++ext2fs_find_first_set_block_bitmap2() returned Invalid argument
++tst_bitmaps: ffsb 12 15
++First marked block is 12
+ tst_bitmaps: clearb 13
+ Clearing block 13, was set before
+ tst_bitmaps: ffzb 12 20
+ First unmarked block is 13
++tst_bitmaps: ffsb 13 18
++First marked block is 14
+ tst_bitmaps: setb 13
+ Setting block 13, was clear before
+ tst_bitmaps: clearb 12 7
+@@ -91,10 +109,24 @@ tst_bitmaps: ffzi 2 5
+ ext2fs_find_first_zero_inode_bitmap2() returned No such file or directory
+ tst_bitmaps: ffzi 2 6
+ First unmarked inode is 6
++tst_bitmaps: ffsi 0 31
++ext2fs_find_first_set_inode_bitmap2() returned Invalid argument
++tst_bitmaps: ffsi 1 33
++ext2fs_find_first_set_inode_bitmap2() returned Invalid argument
++tst_bitmaps: ffsi 1 32
++First marked inode is 2
++tst_bitmaps: ffsi 2 32
++First marked inode is 2
++tst_bitmaps: ffsi 6 32
++ext2fs_find_first_set_inode_bitmap2() returned No such file or directory
+ tst_bitmaps: cleari 4
+ Clearing inode 4, was set before
+ tst_bitmaps: ffzi 2 6
+ First unmarked inode is 4
++tst_bitmaps: ffsi 4 32
++First marked inode is 5
++tst_bitmaps: ffsi 5 32
++First marked inode is 5
+ tst_bitmaps: zeroi
+ Clearing inode bitmap.
+ tst_bitmaps: testi 5
+@@ -207,5 +239,71 @@ Clearing block 7, was set before
+ tst_bitmaps: dump_bb
+ block bitmap: b92a85e6c4680d000000000000000000
+ bits set: 25
++tst_bitmaps: ffsb 14 127
++First marked block is 14
++tst_bitmaps: ffsb 15 127
++First marked block is 17
++tst_bitmaps: ffsb 36 127
++First marked block is 39
++tst_bitmaps: ffsb 32 127
++First marked block is 32
++tst_bitmaps: ffsb 52 127
++First marked block is 52
++tst_bitmaps: ffsb 53 127
++ext2fs_find_first_set_block_bitmap2() returned No such file or directory
++tst_bitmaps: ffsb 46 127
++First marked block is 46
++tst_bitmaps: ffsb 45 127
++First marked block is 46
++tst_bitmaps: ffsb 41 127
++First marked block is 44
++tst_bitmaps: ffsb 20 127
++First marked block is 24
++tst_bitmaps: ffsb 1 127
++First marked block is 1
++tst_bitmaps: ffsb 2 127
++First marked block is 4
++tst_bitmaps: ffsb 3 127
++First marked block is 4
++tst_bitmaps: ffsb 4 127
++First marked block is 4
++tst_bitmaps: ffsb 5 127
++First marked block is 5
++tst_bitmaps: ffsb 6 127
++First marked block is 6
++tst_bitmaps: ffsb 7 127
++First marked block is 8
++tst_bitmaps: ffsb 8 127
++First marked block is 8
++tst_bitmaps: ffzb 1 127
++First unmarked block is 2
++tst_bitmaps: ffzb 2 127
++First unmarked block is 2
++tst_bitmaps: ffzb 3 127
++First unmarked block is 3
++tst_bitmaps: ffzb 4 127
++First unmarked block is 7
++tst_bitmaps: ffzb 5 127
++First unmarked block is 7
++tst_bitmaps: ffzb 6 127
++First unmarked block is 7
++tst_bitmaps: ffzb 7 127
++First unmarked block is 7
++tst_bitmaps: ffzb 8 127
++First unmarked block is 9
++tst_bitmaps: ffzb 45 127
++First unmarked block is 45
++tst_bitmaps: ffzb 46 127
++First unmarked block is 48
++tst_bitmaps: ffzb 47 127
++First unmarked block is 48
++tst_bitmaps: ffzb 48 127
++First unmarked block is 48
++tst_bitmaps: ffzb 49 127
++First unmarked block is 50
++tst_bitmaps: ffzb 50 127
++First unmarked block is 50
++tst_bitmaps: ffzb 51 127
++First unmarked block is 53
+ tst_bitmaps: quit
+ tst_bitmaps:
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/tst_super_size.c
++++ e2fsprogs-1.42.9/lib/ext2fs/tst_super_size.c
+@@ -135,7 +135,8 @@ int main(int argc, char **argv)
+ check_field(s_usr_quota_inum, 4);
+ check_field(s_grp_quota_inum, 4);
+ check_field(s_overhead_blocks, 4);
+- check_field(s_reserved, 108 * 4);
++ check_field(s_backup_bgs, 8);
++ check_field(s_reserved, 106 * 4);
+ check_field(s_checksum, 4);
+ do_field("Superblock end", 0, 0, cur_offset, 1024);
+ #endif
+--- e2fsprogs-1.42.9.orig/lib/ext2fs/unix_io.c
++++ e2fsprogs-1.42.9/lib/ext2fs/unix_io.c
+@@ -931,10 +931,10 @@ static errcode_t unix_discard(io_channel
+
+ if (channel->flags & CHANNEL_FLAGS_BLOCK_DEVICE) {
+ #ifdef BLKDISCARD
+- __uint64_t range[2];
++ __u64 range[2];
+
+- range[0] = (__uint64_t)(block) * channel->block_size;
+- range[1] = (__uint64_t)(count) * channel->block_size;
++ range[0] = (__u64)(block) * channel->block_size;
++ range[1] = (__u64)(count) * channel->block_size;
+
+ ret = ioctl(data->dev, BLKDISCARD, &range);
+ #else
+--- e2fsprogs-1.42.9.orig/lib/quota/Makefile.in
++++ e2fsprogs-1.42.9/lib/quota/Makefile.in
+@@ -135,27 +135,29 @@ mkquota.o: $(srcdir)/mkquota.c $(top_bui
+ $(srcdir)/quotaio_tree.h $(srcdir)/quotaio_v2.h $(srcdir)/mkquota.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h $(srcdir)/common.h
+ quotaio.o: $(srcdir)/quotaio.c $(top_builddir)/lib/config.h \
+- $(top_builddir)/lib/dirpaths.h $(srcdir)/common.h $(srcdir)/quotaio.h \
+- $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \
+- $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \
+- $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \
+- $(top_builddir)/lib/ext2fs/ext2_err.h \
++ $(top_builddir)/lib/dirpaths.h $(srcdir)/common.h \
++ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/quotaio.h \
++ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
++ $(top_srcdir)/lib/ext2fs/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
++ $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \
+ $(srcdir)/dqblk_v2.h $(srcdir)/quotaio_tree.h
+ quotaio_tree.o: $(srcdir)/quotaio_tree.c $(top_builddir)/lib/config.h \
+- $(top_builddir)/lib/dirpaths.h $(srcdir)/common.h $(srcdir)/quotaio_tree.h \
++ $(top_builddir)/lib/dirpaths.h $(srcdir)/common.h \
++ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/quotaio_tree.h \
+ $(srcdir)/quotaio.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
+- $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
+- $(top_srcdir)/lib/ext2fs/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
+- $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
++ $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \
++ $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \
++ $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \
+ $(srcdir)/dqblk_v2.h
+ quotaio_v2.o: $(srcdir)/quotaio_v2.c $(top_builddir)/lib/config.h \
+- $(top_builddir)/lib/dirpaths.h $(srcdir)/common.h $(srcdir)/quotaio_v2.h \
++ $(top_builddir)/lib/dirpaths.h $(srcdir)/common.h \
++ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/quotaio_v2.h \
+ $(srcdir)/quotaio.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
+- $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
+- $(top_srcdir)/lib/ext2fs/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
+- $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
++ $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \
++ $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \
++ $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \
+ $(srcdir)/dqblk_v2.h $(srcdir)/quotaio_tree.h
+ dict.o: $(srcdir)/../../e2fsck/dict.c $(top_builddir)/lib/config.h \
+--- e2fsprogs-1.42.9.orig/lib/quota/common.h
++++ e2fsprogs-1.42.9/lib/quota/common.h
+@@ -7,6 +7,13 @@
+ #ifndef __QUOTA_COMMON_H__
+ #define __QUOTA_COMMON_H__
+
++#if EXT2_FLAT_INCLUDES
++#include "e2_types.h"
++#else
++#include <ext2fs/ext2_types.h>
++#endif /* EXT2_FLAT_INCLUDES */
++
++
+ #ifndef __attribute__
+ # if !defined __GNUC__ || __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
+ # define __attribute__(x)
+--- e2fsprogs-1.42.9.orig/lib/quota/mkquota.c
++++ e2fsprogs-1.42.9/lib/quota/mkquota.c
+@@ -89,8 +89,13 @@ void quota_set_sb_inum(ext2_filsys fs, e
+ errcode_t quota_remove_inode(ext2_filsys fs, int qtype)
+ {
+ ext2_ino_t qf_ino;
++ errcode_t retval;
+
+- ext2fs_read_bitmaps(fs);
++ retval = ext2fs_read_bitmaps(fs);
++ if (retval) {
++ log_err("Couldn't read bitmaps: %s", error_message(retval));
++ return retval;
++ }
+ qf_ino = (qtype == USRQUOTA) ? fs->super->s_usr_quota_inum :
+ fs->super->s_grp_quota_inum;
+ quota_set_sb_inum(fs, 0, qtype);
+@@ -100,7 +105,11 @@ errcode_t quota_remove_inode(ext2_filsys
+
+ ext2fs_mark_super_dirty(fs);
+ fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
+- ext2fs_write_bitmaps(fs);
++ retval = ext2fs_write_bitmaps(fs);
++ if (retval) {
++ log_err("Couldn't write bitmaps: %s", error_message(retval));
++ return retval;
++ }
+ return 0;
+ }
+
+@@ -133,11 +142,16 @@ errcode_t quota_write_inode(quota_ctx_t
+ fs = qctx->fs;
+ retval = ext2fs_get_mem(sizeof(struct quota_handle), &h);
+ if (retval) {
+- log_err("Unable to allocate quota handle");
++ log_err("Unable to allocate quota handle: %s",
++ error_message(retval));
+ goto out;
+ }
+
+- ext2fs_read_bitmaps(fs);
++ retval = ext2fs_read_bitmaps(fs);
++ if (retval) {
++ log_err("Couldn't read bitmaps: %s", error_message(retval));
++ goto out;
++ }
+
+ for (i = 0; i < MAXQUOTAS; i++) {
+ if ((qtype != -1) && (i != qtype))
+@@ -171,7 +185,11 @@ errcode_t quota_write_inode(quota_ctx_t
+ fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
+ }
+
+- ext2fs_write_bitmaps(fs);
++ retval = ext2fs_write_bitmaps(fs);
++ if (retval) {
++ log_err("Couldn't write bitmaps: %s", error_message(retval));
++ goto out;
++ }
+ out:
+ if (h)
+ ext2fs_free_mem(&h);
+--- e2fsprogs-1.42.9.orig/lib/quota/quotaio.c
++++ e2fsprogs-1.42.9/lib/quota/quotaio.c
+@@ -30,8 +30,8 @@ static const char * const basenames[] =
+
+ /* Header in all newer quotafiles */
+ struct disk_dqheader {
+- u_int32_t dqh_magic;
+- u_int32_t dqh_version;
++ __u32 dqh_magic;
++ __u32 dqh_version;
+ } __attribute__ ((packed));
+
+ /**
+--- e2fsprogs-1.42.9.orig/lib/quota/quotaio_tree.c
++++ e2fsprogs-1.42.9/lib/quota/quotaio_tree.c
+@@ -59,7 +59,7 @@ static inline void mark_quotafile_info_d
+ }
+
+ /* Read given block */
+-static void read_blk(struct quota_handle *h, uint blk, dqbuf_t buf)
++static void read_blk(struct quota_handle *h, unsigned int blk, dqbuf_t buf)
+ {
+ int err;
+
+@@ -72,7 +72,7 @@ static void read_blk(struct quota_handle
+ }
+
+ /* Write block */
+-static int write_blk(struct quota_handle *h, uint blk, dqbuf_t buf)
++static int write_blk(struct quota_handle *h, unsigned int blk, dqbuf_t buf)
+ {
+ int err;
+
+@@ -117,7 +117,8 @@ static int get_free_dqblk(struct quota_h
+ }
+
+ /* Put given block to free list */
+-static void put_free_dqblk(struct quota_handle *h, dqbuf_t buf, uint blk)
++static void put_free_dqblk(struct quota_handle *h, dqbuf_t buf,
++ unsigned int blk)
+ {
+ struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
+ struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree;
+@@ -131,11 +132,12 @@ static void put_free_dqblk(struct quota_
+ }
+
+ /* Remove given block from the list of blocks with free entries */
+-static void remove_free_dqentry(struct quota_handle *h, dqbuf_t buf, uint blk)
++static void remove_free_dqentry(struct quota_handle *h, dqbuf_t buf,
++ unsigned int blk)
+ {
+ dqbuf_t tmpbuf = getdqbuf();
+ struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
+- uint nextblk = ext2fs_le32_to_cpu(dh->dqdh_next_free), prevblk =
++ unsigned int nextblk = ext2fs_le32_to_cpu(dh->dqdh_next_free), prevblk =
+
+ ext2fs_le32_to_cpu(dh->dqdh_prev_free);
+
+@@ -164,7 +166,8 @@ static void remove_free_dqentry(struct q
+ }
+
+ /* Insert given block to the beginning of list with free entries */
+-static void insert_free_dqentry(struct quota_handle *h, dqbuf_t buf, uint blk)
++static void insert_free_dqentry(struct quota_handle *h, dqbuf_t buf,
++ unsigned int blk)
+ {
+ dqbuf_t tmpbuf = getdqbuf();
+ struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
+@@ -188,8 +191,8 @@ static void insert_free_dqentry(struct q
+ }
+
+ /* Find space for dquot */
+-static uint find_free_dqentry(struct quota_handle *h, struct dquot *dquot,
+- int *err)
++static unsigned int find_free_dqentry(struct quota_handle *h,
++ struct dquot *dquot, int *err)
+ {
+ int blk, i;
+ struct qt_disk_dqdbheader *dh;
+@@ -247,12 +250,12 @@ static uint find_free_dqentry(struct quo
+
+ /* Insert reference to structure into the trie */
+ static int do_insert_tree(struct quota_handle *h, struct dquot *dquot,
+- uint * treeblk, int depth)
++ unsigned int * treeblk, int depth)
+ {
+ dqbuf_t buf;
+ int newson = 0, newact = 0;
+- u_int32_t *ref;
+- uint newblk;
++ __u32 *ref;
++ unsigned int newblk;
+ int ret = 0;
+
+ log_debug("inserting in tree: treeblk=%u, depth=%d", *treeblk, depth);
+@@ -271,7 +274,7 @@ static int do_insert_tree(struct quota_h
+ read_blk(h, *treeblk, buf);
+ }
+
+- ref = (u_int32_t *) buf;
++ ref = (__u32 *) buf;
+ newblk = ext2fs_le32_to_cpu(ref[get_index(dquot->dq_id, depth)]);
+ if (!newblk)
+ newson = 1;
+@@ -301,11 +304,11 @@ out_buf:
+ /* Wrapper for inserting quota structure into tree */
+ static void dq_insert_tree(struct quota_handle *h, struct dquot *dquot)
+ {
+- uint tmp = QT_TREEOFF;
++ unsigned int tmp = QT_TREEOFF;
+
+ if (do_insert_tree(h, dquot, &tmp, 0) < 0)
+ log_err("Cannot write quota (id %u): %s",
+- (uint) dquot->dq_id, strerror(errno));
++ (unsigned int) dquot->dq_id, strerror(errno));
+ }
+
+ /* Write dquot to file */
+@@ -323,9 +326,10 @@ void qtree_write_dquot(struct dquot *dqu
+ if (ret) {
+ errno = ENOMEM;
+ log_err("Quota write failed (id %u): %s",
+- (uint)dquot->dq_id, strerror(errno));
++ (unsigned int)dquot->dq_id, strerror(errno));
+ return;
+ }
++ memset(ddquot, 0, info->dqi_entry_size);
+
+ if (!dquot->dq_dqb.u.v2_mdqb.dqb_off)
+ dq_insert_tree(dquot->dq_h, dquot);
+@@ -340,13 +344,14 @@ void qtree_write_dquot(struct dquot *dqu
+ if (ret > 0)
+ errno = ENOSPC;
+ log_err("Quota write failed (id %u): %s",
+- (uint)dquot->dq_id, strerror(errno));
++ (unsigned int)dquot->dq_id, strerror(errno));
+ }
+ ext2fs_free_mem(&ddquot);
+ }
+
+ /* Free dquot entry in data block */
+-static void free_dqentry(struct quota_handle *h, struct dquot *dquot, uint blk)
++static void free_dqentry(struct quota_handle *h, struct dquot *dquot,
++ unsigned int blk)
+ {
+ struct qt_disk_dqdbheader *dh;
+ struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree;
+@@ -358,7 +363,7 @@ static void free_dqentry(struct quota_ha
+ if (dquot->dq_dqb.u.v2_mdqb.dqb_off >> QT_BLKSIZE_BITS != blk)
+ log_err("Quota structure has offset to other block (%u) "
+ "than it should (%u).", blk,
+- (uint) (dquot->dq_dqb.u.v2_mdqb.dqb_off >>
++ (unsigned int) (dquot->dq_dqb.u.v2_mdqb.dqb_off >>
+ QT_BLKSIZE_BITS));
+
+ read_blk(h, blk, buf);
+@@ -388,11 +393,11 @@ static void free_dqentry(struct quota_ha
+
+ /* Remove reference to dquot from tree */
+ static void remove_tree(struct quota_handle *h, struct dquot *dquot,
+- uint * blk, int depth)
++ unsigned int * blk, int depth)
+ {
+ dqbuf_t buf = getdqbuf();
+- uint newblk;
+- u_int32_t *ref = (u_int32_t *) buf;
++ unsigned int newblk;
++ __u32 *ref = (__u32 *) buf;
+
+ if (!buf)
+ return;
+@@ -428,7 +433,7 @@ static void remove_tree(struct quota_han
+ /* Delete dquot from tree */
+ void qtree_delete_dquot(struct dquot *dquot)
+ {
+- uint tmp = QT_TREEOFF;
++ unsigned int tmp = QT_TREEOFF;
+
+ if (!dquot->dq_dqb.u.v2_mdqb.dqb_off) /* Even not allocated? */
+ return;
+@@ -437,7 +442,7 @@ void qtree_delete_dquot(struct dquot *dq
+
+ /* Find entry in block */
+ static ext2_loff_t find_block_dqentry(struct quota_handle *h,
+- struct dquot *dquot, uint blk)
++ struct dquot *dquot, unsigned int blk)
+ {
+ struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree;
+ dqbuf_t buf = getdqbuf();
+@@ -464,11 +469,11 @@ static ext2_loff_t find_block_dqentry(st
+ /* Find entry for given id in the tree */
+ static ext2_loff_t find_tree_dqentry(struct quota_handle *h,
+ struct dquot *dquot,
+- uint blk, int depth)
++ unsigned int blk, int depth)
+ {
+ dqbuf_t buf = getdqbuf();
+ ext2_loff_t ret = 0;
+- u_int32_t *ref = (u_int32_t *) buf;
++ __u32 *ref = (__u32 *) buf;
+
+ if (!buf)
+ return -ENOMEM;
+@@ -540,7 +545,7 @@ struct dquot *qtree_read_dquot(struct qu
+ #define set_bit(bmp, ind) ((bmp)[(ind) >> 3] |= (1 << ((ind) & 7)))
+ #define get_bit(bmp, ind) ((bmp)[(ind) >> 3] & (1 << ((ind) & 7)))
+
+-static int report_block(struct dquot *dquot, uint blk, char *bitmap,
++static int report_block(struct dquot *dquot, unsigned int blk, char *bitmap,
+ int (*process_dquot) (struct dquot *, void *),
+ void *data)
+ {
+@@ -574,7 +579,7 @@ static int report_block(struct dquot *dq
+ return entries;
+ }
+
+-static void check_reference(struct quota_handle *h, uint blk)
++static void check_reference(struct quota_handle *h, unsigned int blk)
+ {
+ if (blk >= h->qh_info.u.v2_mdqi.dqi_qtree.dqi_blocks)
+ log_err("Illegal reference (%u >= %u) in %s quota file. "
+@@ -585,13 +590,14 @@ static void check_reference(struct quota
+ type2name(h->qh_type));
+ }
+
+-static int report_tree(struct dquot *dquot, uint blk, int depth, char *bitmap,
++static int report_tree(struct dquot *dquot, unsigned int blk, int depth,
++ char *bitmap,
+ int (*process_dquot) (struct dquot *, void *),
+ void *data)
+ {
+ int entries = 0, i;
+ dqbuf_t buf = getdqbuf();
+- u_int32_t *ref = (u_int32_t *) buf;
++ __u32 *ref = (__u32 *) buf;
+
+ if (!buf)
+ return 0;
+@@ -620,9 +626,9 @@ static int report_tree(struct dquot *dqu
+ return entries;
+ }
+
+-static uint find_set_bits(char *bmp, int blocks)
++static unsigned int find_set_bits(char *bmp, int blocks)
+ {
+- uint i, used = 0;
++ unsigned int i, used = 0;
+
+ for (i = 0; i < blocks; i++)
+ if (get_bit(bmp, i))
+--- e2fsprogs-1.42.9.orig/lib/quota/quotaio_tree.h
++++ e2fsprogs-1.42.9/lib/quota/quotaio_tree.h
+@@ -7,7 +7,7 @@
+
+ #include <sys/types.h>
+
+-typedef u_int32_t qid_t; /* Type in which we store ids in memory */
++typedef __u32 qid_t; /* Type in which we store ids in memory */
+
+ #define QT_TREEOFF 1 /* Offset of tree in file in blocks */
+ #define QT_TREEDEPTH 4 /* Depth of quota tree */
+@@ -20,13 +20,13 @@ typedef u_int32_t qid_t; /* Type
+ * so there will be space for exactly 21 quota-entries in a block
+ */
+ struct qt_disk_dqdbheader {
+- u_int32_t dqdh_next_free; /* Number of next block with free
++ __u32 dqdh_next_free; /* Number of next block with free
+ * entry */
+- u_int32_t dqdh_prev_free; /* Number of previous block with free
++ __u32 dqdh_prev_free; /* Number of previous block with free
+ * entry */
+- u_int16_t dqdh_entries; /* Number of valid entries in block */
+- u_int16_t dqdh_pad1;
+- u_int32_t dqdh_pad2;
++ __u16 dqdh_entries; /* Number of valid entries in block */
++ __u16 dqdh_pad1;
++ __u32 dqdh_pad2;
+ } __attribute__ ((packed));
+
+ struct dquot;
+--- e2fsprogs-1.42.9.orig/lib/quota/quotaio_v2.h
++++ e2fsprogs-1.42.9/lib/quota/quotaio_v2.h
+@@ -16,8 +16,8 @@
+ #define V2_VERSION 1
+
+ struct v2_disk_dqheader {
+- u_int32_t dqh_magic; /* Magic number identifying file */
+- u_int32_t dqh_version; /* File version */
++ __u32 dqh_magic; /* Magic number identifying file */
++ __u32 dqh_version; /* File version */
+ } __attribute__ ((packed));
+
+ /* Flags for version specific files */
+@@ -25,30 +25,30 @@ struct v2_disk_dqheader {
+
+ /* Header with type and version specific information */
+ struct v2_disk_dqinfo {
+- u_int32_t dqi_bgrace; /* Time before block soft limit becomes
++ __u32 dqi_bgrace; /* Time before block soft limit becomes
+ * hard limit */
+- u_int32_t dqi_igrace; /* Time before inode soft limit becomes
++ __u32 dqi_igrace; /* Time before inode soft limit becomes
+ * hard limit */
+- u_int32_t dqi_flags; /* Flags for quotafile (DQF_*) */
+- u_int32_t dqi_blocks; /* Number of blocks in file */
+- u_int32_t dqi_free_blk; /* Number of first free block in the list */
+- u_int32_t dqi_free_entry; /* Number of block with at least one
++ __u32 dqi_flags; /* Flags for quotafile (DQF_*) */
++ __u32 dqi_blocks; /* Number of blocks in file */
++ __u32 dqi_free_blk; /* Number of first free block in the list */
++ __u32 dqi_free_entry; /* Number of block with at least one
+ * free entry */
+ } __attribute__ ((packed));
+
+ struct v2r1_disk_dqblk {
+- u_int32_t dqb_id; /* id this quota applies to */
+- u_int32_t dqb_pad;
+- u_int64_t dqb_ihardlimit; /* absolute limit on allocated inodes */
+- u_int64_t dqb_isoftlimit; /* preferred inode limit */
+- u_int64_t dqb_curinodes; /* current # allocated inodes */
+- u_int64_t dqb_bhardlimit; /* absolute limit on disk space
++ __u32 dqb_id; /* id this quota applies to */
++ __u32 dqb_pad;
++ __u64 dqb_ihardlimit; /* absolute limit on allocated inodes */
++ __u64 dqb_isoftlimit; /* preferred inode limit */
++ __u64 dqb_curinodes; /* current # allocated inodes */
++ __u64 dqb_bhardlimit; /* absolute limit on disk space
+ * (in QUOTABLOCK_SIZE) */
+- u_int64_t dqb_bsoftlimit; /* preferred limit on disk space
++ __u64 dqb_bsoftlimit; /* preferred limit on disk space
+ * (in QUOTABLOCK_SIZE) */
+- u_int64_t dqb_curspace; /* current space occupied (in bytes) */
+- u_int64_t dqb_btime; /* time limit for excessive disk use */
+- u_int64_t dqb_itime; /* time limit for excessive inode use */
++ __u64 dqb_curspace; /* current space occupied (in bytes) */
++ __u64 dqb_btime; /* time limit for excessive disk use */
++ __u64 dqb_itime; /* time limit for excessive inode use */
+ } __attribute__ ((packed));
+
+ #endif
+--- e2fsprogs-1.42.9.orig/lib/ss/Makefile.in
++++ e2fsprogs-1.42.9/lib/ss/Makefile.in
+@@ -162,7 +162,7 @@ uninstall::
+ test_ss: test_ss.o test_cmd.o $(DEPLIBSS) $(DEPLIBCOM_ERR)
+ $(E) " LD $@"
+ $(Q) $(CC) -o $@ test_ss.o test_cmd.o $(ALL_CFLAGS) \
+- $(LIBSS) $(LIBCOM_ERR)
++ $(LIBSS) $(LIBCOM_ERR) $(SYSLIBS)
+
+ check:: all test_ss
+ $(E) " RUN TEST test_ss"
+--- e2fsprogs-1.42.9.orig/lib/ss/invocation.c
++++ e2fsprogs-1.42.9/lib/ss/invocation.c
+@@ -45,7 +45,8 @@ int ss_create_invocation(const char *sub
+ table = (ss_data **) realloc((char *)table,
+ ((unsigned)sci_idx+2)*size);
+ if (table == NULL) {
+- *code_ptr = errno;
++ *code_ptr = ENOMEM;
++ free(new_table);
+ return 0;
+ }
+ table[sci_idx+1] = (ss_data *) NULL;
+--- e2fsprogs-1.42.9.orig/lib/ss/list_rqs.c
++++ e2fsprogs-1.42.9/lib/ss/list_rqs.c
+@@ -18,20 +18,15 @@
+
+ typedef void sigret_t;
+
+-static char const twentyfive_spaces[26] =
+- " ";
+-static char const NL[2] = "\n";
+-
+ void ss_list_requests(int argc __SS_ATTR((unused)),
+ const char * const *argv __SS_ATTR((unused)),
+ int sci_idx, void *infop __SS_ATTR((unused)))
+ {
+ ss_request_entry *entry;
+ char const * const *name;
+- int spacing;
++ int i, spacing;
+ ss_request_table **table;
+
+- char buffer[BUFSIZ];
+ FILE *output;
+ int fd;
+ sigset_t omask, igmask;
+@@ -60,27 +55,24 @@ void ss_list_requests(int argc __SS_ATTR
+ entry = (*table)->requests;
+ for (; entry->command_names; entry++) {
+ spacing = -2;
+- buffer[0] = '\0';
+ if (entry->flags & SS_OPT_DONT_LIST)
+ continue;
+ for (name = entry->command_names; *name; name++) {
+ int len = strlen(*name);
+- strncat(buffer, *name, len);
++ fputs(*name, output);
+ spacing += len + 2;
+ if (name[1]) {
+- strcat(buffer, ", ");
++ fputs(", ", output);
+ }
+ }
+ if (spacing > 23) {
+- strcat(buffer, NL);
+- fputs(buffer, output);
++ fputc('\n', output);
+ spacing = 0;
+- buffer[0] = '\0';
+ }
+- strncat(buffer, twentyfive_spaces, 25-spacing);
+- strcat(buffer, entry->info_string);
+- strcat(buffer, NL);
+- fputs(buffer, output);
++ for (i = 0; i < 25 - spacing; i++)
++ fputc(' ', output);
++ fputs(entry->info_string, output);
++ fputc('\n', output);
+ }
+ }
+ fclose(output);
+--- e2fsprogs-1.42.9.orig/lib/ss/parse.c
++++ e2fsprogs-1.42.9/lib/ss/parse.c
+@@ -45,7 +45,7 @@ enum parse_mode { WHITESPACE, TOKEN, QUO
+
+ char **ss_parse(int sci_idx, register char *line_ptr, int *argc_ptr)
+ {
+- register char **argv, *cp;
++ register char **argv, **new_argv, *cp;
+ register int argc;
+ register enum parse_mode parse_mode;
+
+@@ -78,7 +78,13 @@ char **ss_parse(int sci_idx, register ch
+ /* go to quoted-string mode */
+ parse_mode = QUOTED_STRING;
+ cp = line_ptr++;
+- argv = NEW_ARGV (argv, argc);
++ new_argv = NEW_ARGV (argv, argc);
++ if (new_argv == NULL) {
++ free(argv);
++ *argc_ptr = 0;
++ return NULL;
++ }
++ argv = new_argv;
+ argv[argc++] = cp;
+ argv[argc] = NULL;
+ }
+@@ -86,11 +92,13 @@ char **ss_parse(int sci_idx, register ch
+ /* random-token mode */
+ parse_mode = TOKEN;
+ cp = line_ptr;
+- argv = NEW_ARGV (argv, argc);
+- if (argv == NULL) {
+- *argc_ptr = errno;
+- return argv;
++ new_argv = NEW_ARGV (argv, argc);
++ if (new_argv == NULL) {
++ free(argv);
++ *argc_ptr = 0;
++ return NULL;
+ }
++ argv = new_argv;
+ argv[argc++] = line_ptr;
+ argv[argc] = NULL;
+ }
+--- e2fsprogs-1.42.9.orig/lib/uuid/gen_uuid.c
++++ e2fsprogs-1.42.9/lib/uuid/gen_uuid.c
+@@ -326,10 +326,12 @@ static int get_clock(uint32_t *clock_hig
+ state_fd = open("/var/lib/libuuid/clock.txt",
+ O_RDWR|O_CREAT, 0660);
+ (void) umask(save_umask);
+- state_f = fdopen(state_fd, "r+");
+- if (!state_f) {
+- close(state_fd);
+- state_fd = -1;
++ if (state_fd >= 0) {
++ state_f = fdopen(state_fd, "r+");
++ if (!state_f) {
++ close(state_fd);
++ state_fd = -1;
++ }
+ }
+ }
+ fl.l_type = F_WRLCK;
+@@ -343,7 +345,6 @@ static int get_clock(uint32_t *clock_hig
+ if ((errno == EAGAIN) || (errno == EINTR))
+ continue;
+ fclose(state_f);
+- close(state_fd);
+ state_fd = -1;
+ break;
+ }
+@@ -412,7 +413,10 @@ try_again:
+ }
+ rewind(state_f);
+ fl.l_type = F_UNLCK;
+- fcntl(state_fd, F_SETLK, &fl);
++ if (fcntl(state_fd, F_SETLK, &fl) < 0) {
++ fclose(state_f);
++ state_fd = -1;
++ }
+ }
+
+ *clock_high = clock_reg >> 32;
+--- e2fsprogs-1.42.9.orig/lib/uuid/tst_uuid.c
++++ e2fsprogs-1.42.9/lib/uuid/tst_uuid.c
+@@ -154,7 +154,10 @@ main(int argc ATTR((unused)) , char **ar
+ printf("UUID time comparison succeeded.\n");
+ }
+
+- uuid_parse(str, tst);
++ if (uuid_parse(str, tst) < 0) {
++ printf("UUID parse failed\n");
++ failed++;
++ }
+ if (!uuid_compare(buf, tst)) {
+ printf("UUID parse and compare succeeded.\n");
+ } else {
+--- e2fsprogs-1.42.9.orig/misc/Makefile.in
++++ e2fsprogs-1.42.9/misc/Makefile.in
+@@ -42,7 +42,8 @@ LPROGS= @E2INITRD_PROG@
+
+ TUNE2FS_OBJS= tune2fs.o util.o
+ MKLPF_OBJS= mklost+found.o
+-MKE2FS_OBJS= mke2fs.o util.o profile.o prof_err.o default_profile.o
++MKE2FS_OBJS= mke2fs.o util.o profile.o prof_err.o default_profile.o \
++ mk_hugefiles.o
+ CHATTR_OBJS= chattr.o
+ LSATTR_OBJS= lsattr.o
+ UUIDGEN_OBJS= uuidgen.o
+@@ -76,7 +77,7 @@ PROFILED_E2FREEFRAG_OBJS= profiled/e2fre
+ PROFILED_E2UNDO_OBJS= profiled/e2undo.o
+ PROFILED_E4DEFRAG_OBJS= profiled/e4defrag.o
+
+-SRCS= $(srcdir)/tune2fs.c $(srcdir)/mklost+found.c $(srcdir)/mke2fs.c \
++SRCS= $(srcdir)/tune2fs.c $(srcdir)/mklost+found.c $(srcdir)/mke2fs.c $(srcdir)/mk_hugefiles.c \
+ $(srcdir)/chattr.c $(srcdir)/lsattr.c $(srcdir)/dumpe2fs.c \
+ $(srcdir)/badblocks.c $(srcdir)/fsck.c $(srcdir)/util.c \
+ $(srcdir)/uuidgen.c $(srcdir)/blkid.c $(srcdir)/logsave.c \
+@@ -84,12 +85,12 @@ SRCS= $(srcdir)/tune2fs.c $(srcdir)/mklo
+ $(srcdir)/ismounted.c $(srcdir)/../e2fsck/profile.c \
+ $(srcdir)/e2undo.c $(srcdir)/e2freefrag.c
+
+-LIBS= $(LIBEXT2FS) $(LIBCOM_ERR)
++LIBS= $(LIBEXT2FS) $(LIBCOM_ERR)
+ DEPLIBS= $(LIBEXT2FS) $(DEPLIBCOM_ERR)
+ PROFILED_LIBS= $(PROFILED_LIBEXT2FS) $(PROFILED_LIBCOM_ERR)
+ PROFILED_DEPLIBS= $(PROFILED_LIBEXT2FS) $(DEPPROFILED_LIBCOM_ERR)
+
+-STATIC_LIBS= $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR)
++STATIC_LIBS= $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR)
+ STATIC_DEPLIBS= $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR)
+
+ LIBS_E2P= $(LIBE2P) $(LIBCOM_ERR)
+@@ -142,7 +143,7 @@ profile.o:
+
+ findsuper: findsuper.o
+ $(E) " LD $@"
+- $(Q) $(CC) $(ALL_LDFLAGS) -o findsuper findsuper.o $(LIBS)
++ $(Q) $(CC) $(ALL_LDFLAGS) -o findsuper findsuper.o $(LIBS) $(SYSLIBS)
+
+ partinfo: partinfo.o
+ $(E) " LD $@"
+@@ -151,20 +152,20 @@ partinfo: partinfo.o
+ e2initrd_helper: e2initrd_helper.o $(DEPLIBS) $(DEPLIBBLKID) $(LIBEXT2FS)
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -o e2initrd_helper e2initrd_helper.o $(LIBS) \
+- $(LIBBLKID) $(LIBEXT2FS) $(LIBINTL)
++ $(LIBBLKID) $(LIBEXT2FS) $(LIBINTL) $(SYSLIBS)
+
+ tune2fs: $(TUNE2FS_OBJS) $(DEPLIBS) $(DEPLIBS_E2P) $(DEPLIBBLKID) \
+ $(DEPLIBUUID) $(DEPLIBQUOTA) $(LIBEXT2FS)
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -o tune2fs $(TUNE2FS_OBJS) $(LIBS) \
+ $(LIBBLKID) $(LIBUUID) $(LIBQUOTA) $(LIBEXT2FS) $(LIBS_E2P) \
+- $(LIBINTL)
++ $(LIBINTL) $(SYSLIBS)
+
+ tune2fs.static: $(TUNE2FS_OBJS) $(STATIC_DEPLIBS) $(STATIC_LIBE2P) $(DEPSTATIC_LIBBLKID)
+ $(E) " LD $@"
+ $(Q) $(CC) $(LDFLAGS_STATIC) -o tune2fs.static $(TUNE2FS_OBJS) \
+ $(STATIC_LIBS) $(STATIC_LIBBLKID) $(STATIC_LIBUUID) \
+- $(STATIC_LIBQUOTA) $(STATIC_LIBE2P) $(LIBINTL)
++ $(STATIC_LIBQUOTA) $(STATIC_LIBE2P) $(LIBINTL) $(SYSLIBS)
+
+ tune2fs.profiled: $(TUNE2FS_OBJS) $(PROFILED_DEPLIBS) \
+ $(PROFILED_E2P) $(DEPPROFILED_LIBBLKID) $(DEPPROFILED_LIBUUID) \
+@@ -173,55 +174,58 @@ tune2fs.profiled: $(TUNE2FS_OBJS) $(PROF
+ $(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o tune2fs.profiled \
+ $(PROFILED_TUNE2FS_OBJS) $(PROFILED_LIBBLKID) \
+ $(PROFILED_LIBUUID) $(PROFILED_LIBQUOTA) $(PROFILED_LIBE2P) \
+- $(LIBINTL) $(PROFILED_LIBS)
++ $(LIBINTL) $(PROFILED_LIBS) $(SYSLIBS)
+
+ blkid: $(BLKID_OBJS) $(DEPLIBBLKID) $(LIBEXT2FS)
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -o blkid $(BLKID_OBJS) $(LIBBLKID) $(LIBINTL) \
+- $(LIBEXT2FS)
++ $(LIBEXT2FS) $(SYSLIBS)
+
+ blkid.static: $(BLKID_OBJS) $(STATIC_DEPLIBS) $(DEPSTATIC_LIBBLKID)
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -o blkid.static $(BLKID_OBJS) $(STATIC_LIBS) \
+- $(STATIC_LIBBLKID) $(LIBINTL)
++ $(STATIC_LIBBLKID) $(LIBINTL) $(SYSLIBS)
+
+ blkid.profiled: $(BLKID_OBJS) $(DEPPROFILED_LIBBLKID) \
+ $(PROFILED_LIBEXT2FS)
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o blkid.profiled $(PROFILED_BLKID_OBJS) \
+- $(PROFILED_LIBBLKID) $(LIBINTL) $(PROFILED_LIBEXT2FS)
++ $(PROFILED_LIBBLKID) $(LIBINTL) $(PROFILED_LIBEXT2FS) $(SYSLIBS)
+
+ e2image: $(E2IMAGE_OBJS) $(DEPLIBS)
+ $(E) " LD $@"
+- $(Q) $(CC) $(ALL_LDFLAGS) -o e2image $(E2IMAGE_OBJS) $(LIBS) $(LIBINTL)
++ $(Q) $(CC) $(ALL_LDFLAGS) -o e2image $(E2IMAGE_OBJS) $(LIBS) \
++ $(LIBINTL) $(SYSLIBS)
+
+ e2image.profiled: $(E2IMAGE_OBJS) $(PROFILED_DEPLIBS)
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o e2image.profiled \
+- $(PROFILED_E2IMAGE_OBJS) $(PROFILED_LIBS) $(LIBINTL)
++ $(PROFILED_E2IMAGE_OBJS) $(PROFILED_LIBS) $(LIBINTL) $(SYSLIBS)
+
+ e2undo: $(E2UNDO_OBJS) $(DEPLIBS)
+ $(E) " LD $@"
+- $(Q) $(CC) $(ALL_LDFLAGS) -o e2undo $(E2UNDO_OBJS) $(LIBS) $(LIBINTL)
++ $(Q) $(CC) $(ALL_LDFLAGS) -o e2undo $(E2UNDO_OBJS) $(LIBS) \
++ $(LIBINTL) $(SYSLIBS)
+
+ e2undo.profiled: $(E2UNDO_OBJS) $(PROFILED_DEPLIBS)
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o e2undo.profiled \
+- $(PROFILED_E2UNDO_OBJS) $(PROFILED_LIBS) $(LIBINTL)
++ $(PROFILED_E2UNDO_OBJS) $(PROFILED_LIBS) $(LIBINTL) $(SYSLIBS)
+
+ e4defrag: $(E4DEFRAG_OBJS) $(DEPLIBS)
+ $(E) " LD $@"
+- $(Q) $(CC) $(ALL_LDFLAGS) -o e4defrag $(E4DEFRAG_OBJS) $(LIBS)
++ $(Q) $(CC) $(ALL_LDFLAGS) -o e4defrag $(E4DEFRAG_OBJS) $(LIBS) \
++ $(SYSLIBS)
+
+ e4defrag.profiled: $(E4DEFRAG_OBJS) $(PROFILED_DEPLIBS)
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o e4defrag.profiled \
+- $(PROFILED_E4DEFRAG_OBJS) $(PROFILED_LIBS)
++ $(PROFILED_E4DEFRAG_OBJS) $(PROFILED_LIBS) $(SYSLIBS)
+
+ base_device: base_device.c
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) $(srcdir)/base_device.c \
+- -DDEBUG -o base_device
++ -DDEBUG -o base_device $(SYSLIBS)
+
+ check:: base_device
+ ./base_device < $(srcdir)/base_device.tst > base_device.out
+@@ -229,20 +233,22 @@ check:: base_device
+
+ mklost+found: $(MKLPF_OBJS)
+ $(E) " LD $@"
+- $(Q) $(CC) $(ALL_LDFLAGS) -o mklost+found $(MKLPF_OBJS) $(LIBINTL)
++ $(Q) $(CC) $(ALL_LDFLAGS) -o mklost+found $(MKLPF_OBJS) \
++ $(LIBINTL) $(SYSLIBS)
+
+ mke2fs: $(MKE2FS_OBJS) $(DEPLIBS) $(LIBE2P) $(DEPLIBBLKID) $(DEPLIBUUID) \
+ $(DEPLIBQUOTA) $(LIBEXT2FS)
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -o mke2fs $(MKE2FS_OBJS) $(LIBS) $(LIBBLKID) \
+- $(LIBUUID) $(LIBQUOTA) $(LIBEXT2FS) $(LIBE2P) $(LIBINTL)
++ $(LIBUUID) $(LIBQUOTA) $(LIBEXT2FS) $(LIBE2P) $(LIBINTL) \
++ $(SYSLIBS)
+
+ mke2fs.static: $(MKE2FS_OBJS) $(STATIC_DEPLIBS) $(STATIC_LIBE2P) $(DEPSTATIC_LIBUUID) \
+ $(DEPSTATIC_LIBQUOTA) $(DEPSTATIC_LIBBLKID)
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -static -o mke2fs.static $(MKE2FS_OBJS) \
+ $(STATIC_LIBQUOTA) $(STATIC_LIBS) $(STATIC_LIBE2P) \
+- $(STATIC_LIBBLKID) $(STATIC_LIBUUID) $(LIBINTL)
++ $(STATIC_LIBBLKID) $(STATIC_LIBUUID) $(LIBINTL) $(SYSLIBS)
+
+ mke2fs.profiled: $(MKE2FS_OBJS) $(PROFILED_DEPLIBS) \
+ $(PROFILED_LIBE2P) $(PROFILED_DEPLIBBLKID) $(PROFILED_DEPLIBUUID) \
+@@ -250,85 +256,95 @@ mke2fs.profiled: $(MKE2FS_OBJS) $(PROFIL
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o mke2fs.profiled \
+ $(PROFILED_MKE2FS_OBJS) $(PROFILED_LIBBLKID) \
+- $(PROFILED_LIBUUID) $(PROFILED_LIBQUOTA) $(PROFILED_LIBE2P) $(LIBINTL) \
+- $(PROFILED_LIBS)
++ $(PROFILED_LIBUUID) $(PROFILED_LIBQUOTA) $(PROFILED_LIBE2P) \
++ $(LIBINTL) $(PROFILED_LIBS) $(SYSLIBS)
+
+ chattr: $(CHATTR_OBJS) $(DEPLIBS_E2P)
+ $(E) " LD $@"
+- $(Q) $(CC) $(ALL_LDFLAGS) -o chattr $(CHATTR_OBJS) $(LIBS_E2P) $(LIBINTL)
++ $(Q) $(CC) $(ALL_LDFLAGS) -o chattr $(CHATTR_OBJS) $(LIBS_E2P) \
++ $(LIBINTL) $(SYSLIBS)
+
+ lsattr: $(LSATTR_OBJS) $(DEPLIBS_E2P)
+ $(E) " LD $@"
+- $(Q) $(CC) $(ALL_LDFLAGS) -o lsattr $(LSATTR_OBJS) $(LIBS_E2P) $(LIBINTL)
++ $(Q) $(CC) $(ALL_LDFLAGS) -o lsattr $(LSATTR_OBJS) $(LIBS_E2P) \
++ $(LIBINTL) $(SYSLIBS)
+
+ uuidgen: $(UUIDGEN_OBJS) $(DEPLIBUUID)
+ $(E) " LD $@"
+- $(Q) $(CC) $(ALL_LDFLAGS) -o uuidgen $(UUIDGEN_OBJS) $(LIBUUID) $(LIBINTL)
++ $(Q) $(CC) $(ALL_LDFLAGS) -o uuidgen $(UUIDGEN_OBJS) $(LIBUUID) \
++ $(LIBINTL) $(SYSLIBS)
+
+ uuidgen.profiled: $(UUIDGEN_OBJS) $(PROFILED_DEPLIBUUID)
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o uuidgen.profiled \
+- $(PROFILED_UUIDGEN_OBJS) $(PROFILED_LIBUUID) $(LIBINTL)
++ $(PROFILED_UUIDGEN_OBJS) $(PROFILED_LIBUUID) $(LIBINTL) \
++ $(SYSLIBS)
+
+ uuidd: $(UUIDD_OBJS) $(DEPLIBUUID)
+ $(E) " LD $@"
+- $(Q) $(CC) $(ALL_LDFLAGS) -o uuidd $(UUIDD_OBJS) $(LIBUUID) $(LIBINTL)
++ $(Q) $(CC) $(ALL_LDFLAGS) -o uuidd $(UUIDD_OBJS) $(LIBUUID) \
++ $(LIBINTL) $(SYSLIBS)
+
+ uuidd.profiled: $(UUIDD_OBJS) $(PROFILED_DEPLIBUUID)
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o uuidd.profiled $(PROFILED_UUIDD_OBJS) \
+- $(PROFILED_LIBUUID) $(LIBINTL)
++ $(PROFILED_LIBUUID) $(LIBINTL) $(SYSLIBS)
+
+ dumpe2fs: $(DUMPE2FS_OBJS) $(DEPLIBS) $(DEPLIBS_E2P) $(DEPLIBUUID)
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -o dumpe2fs $(DUMPE2FS_OBJS) $(LIBS) \
+- $(LIBS_E2P) $(LIBUUID) $(LIBINTL)
++ $(LIBS_E2P) $(LIBUUID) $(LIBINTL) $(SYSLIBS)
+
+ dumpe2fs.profiled: $(DUMPE2FS_OBJS) $(PROFILED_DEPLIBS) \
+ $(PROFILED_LIBE2P) $(PROFILED_DEPLIBUUID)
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o dumpe2fs.profiled \
+ $(PROFILED_DUMPE2FS_OBJS) $(PROFILED_LIBS) \
+- $(PROFILED_LIBE2P) $(PROFILED_LIBUUID) $(LIBINTL)
++ $(PROFILED_LIBE2P) $(PROFILED_LIBUUID) $(LIBINTL) $(SYSLIBS)
+
+ fsck: $(FSCK_OBJS) $(DEPLIBBLKID)
+ $(E) " LD $@"
+- $(Q) $(CC) $(ALL_LDFLAGS) -o fsck $(FSCK_OBJS) $(LIBBLKID) $(LIBINTL)
++ $(Q) $(CC) $(ALL_LDFLAGS) -o fsck $(FSCK_OBJS) $(LIBBLKID) \
++ $(LIBINTL) $(SYSLIBS)
+
+ fsck.profiled: $(FSCK_OBJS) $(PROFILED_DEPLIBBLKID)
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o fsck.profiled $(PROFILED_FSCK_OBJS) \
+- $(PROFILED_LIBBLKID) $(LIBINTL)
++ $(PROFILED_LIBBLKID) $(LIBINTL) $(SYSLIBS)
+
+ badblocks: $(BADBLOCKS_OBJS) $(DEPLIBS)
+ $(E) " LD $@"
+- $(Q) $(CC) $(ALL_LDFLAGS) -o badblocks $(BADBLOCKS_OBJS) $(LIBS) $(LIBINTL)
++ $(Q) $(CC) $(ALL_LDFLAGS) -o badblocks $(BADBLOCKS_OBJS) $(LIBS) \
++ $(LIBINTL) $(SYSLIBS)
+
+ badblocks.profiled: $(BADBLOCKS_OBJS) $(PROFILED_DEPLIBS)
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o badblocks.profiled \
+- $(PROFILED_BADBLOCKS_OBJS) $(PROFILED_LIBS) $(LIBINTL)
++ $(PROFILED_BADBLOCKS_OBJS) $(PROFILED_LIBS) $(LIBINTL) \
++ $(SYSLIBS)
+
+ logsave: logsave.o
+ $(E) " LD $@"
+- $(Q) $(CC) $(ALL_LDFLAGS) -o logsave logsave.o
++ $(Q) $(CC) $(ALL_LDFLAGS) -o logsave logsave.o $(SYSLIBS)
+
+ logsave.profiled: logsave.o
+ $(E) " LD $@"
+- $(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o logsave.profiled profiled/logsave.o
++ $(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o logsave.profiled \
++ profiled/logsave.o $(SYSLIBS)
+
+ e2freefrag: $(E2FREEFRAG_OBJS)
+ $(E) " LD $@"
+- $(Q) $(CC) $(ALL_LDFLAGS) -o e2freefrag $(E2FREEFRAG_OBJS) $(LIBS)
++ $(Q) $(CC) $(ALL_LDFLAGS) -o e2freefrag $(E2FREEFRAG_OBJS) \
++ $(LIBS) $(SYSLIBS)
+
+ e2freefrag.profiled: $(E2FREEFRAG_OBJS) $(PROFILED_DEPLIBS)
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o e2freefrag.profiled \
+- $(PROFILED_E2FREEFRAG_OBJS) $(PROFILED_LIBS)
++ $(PROFILED_E2FREEFRAG_OBJS) $(PROFILED_LIBS) $(SYSLIBS)
+
+ filefrag: $(FILEFRAG_OBJS)
+ $(E) " LD $@"
+- $(Q) $(CC) $(ALL_LDFLAGS) -o filefrag $(FILEFRAG_OBJS)
++ $(Q) $(CC) $(ALL_LDFLAGS) -o filefrag $(FILEFRAG_OBJS) $(SYSLIBS)
+
+ filefrag.profiled: $(FILEFRAG_OBJS)
+ $(E) " LD $@"
+@@ -338,7 +354,7 @@ filefrag.profiled: $(FILEFRAG_OBJS)
+ tst_ismounted: $(srcdir)/ismounted.c $(STATIC_LIBEXT2FS) $(DEPLIBCOM_ERR)
+ $(E) " LD $@"
+ $(CC) -o tst_ismounted $(srcdir)/ismounted.c -DDEBUG $(ALL_CFLAGS) \
+- $(LIBCOM_ERR)
++ $(LIBCOM_ERR) $(SYSLIBS)
+
+ tune2fs.8: $(DEP_SUBSTITUTE) $(srcdir)/tune2fs.8.in
+ $(E) " SUBST $@"
+@@ -632,7 +648,18 @@ mke2fs.o: $(srcdir)/mke2fs.c $(top_build
+ $(srcdir)/util.h profile.h prof_err.h $(top_srcdir)/version.h \
+ $(srcdir)/nls-enable.h $(top_srcdir)/lib/quota/mkquota.h \
+ $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
+- $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h
++ $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h \
++ $(srcdir)/mke2fs.h
++mk_hugefiles.o: $(srcdir)/mk_hugefiles.c $(top_builddir)/lib/config.h \
++ $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
++ $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2fsP.h \
++ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \
++ $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \
++ $(top_builddir)/lib/ext2fs/ext2_err.h \
++ $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \
++ $(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
++ $(srcdir)/util.h profile.h prof_err.h $(srcdir)/nls-enable.h \
++ $(srcdir)/mke2fs.h
+ chattr.o: $(srcdir)/chattr.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/et/com_err.h \
+--- e2fsprogs-1.42.9.orig/misc/badblocks.c
++++ e2fsprogs-1.42.9/misc/badblocks.c
+@@ -300,7 +300,8 @@ static void set_o_direct(int dev, unsign
+ flag = fcntl(dev, F_GETFL);
+ if (flag > 0) {
+ flag = (flag & ~O_DIRECT) | new_flag;
+- fcntl(dev, F_SETFL, flag);
++ if (fcntl(dev, F_SETFL, flag) < 0)
++ perror("set_o_direct");
+ }
+ current_O_DIRECT = new_flag;
+ }
+--- e2fsprogs-1.42.9.orig/misc/blkid.c
++++ e2fsprogs-1.42.9/misc/blkid.c
+@@ -38,7 +38,7 @@ extern int optind;
+ #include "ext2fs/ext2fs.h"
+ #include "blkid/blkid.h"
+
+-const char *progname = "blkid";
++static const char *progname = "blkid";
+
+ static void print_version(FILE *out)
+ {
+@@ -100,19 +100,27 @@ static int get_terminal_width(void)
+ struct winsize w_win;
+ #endif
+ const char *cp;
++ int width = 80;
+
+ #ifdef TIOCGSIZE
+- if (ioctl (0, TIOCGSIZE, &t_win) == 0)
+- return (t_win.ts_cols);
++ if (ioctl (0, TIOCGSIZE, &t_win) == 0) {
++ width = t_win.ts_cols;
++ goto got_it;
++ }
+ #endif
+ #ifdef TIOCGWINSZ
+- if (ioctl (0, TIOCGWINSZ, &w_win) == 0)
+- return (w_win.ws_col);
++ if (ioctl (0, TIOCGWINSZ, &w_win) == 0) {
++ width = w_win.ws_col;
++ goto got_it;
++ }
+ #endif
+ cp = getenv("COLUMNS");
+ if (cp)
+- return strtol(cp, NULL, 10);
+- return 80;
++ width = atoi(cp);
++got_it:
++ if (width > 4096)
++ return 4096; /* sanity check */
++ return width;
+ }
+
+ static int pretty_print_word(const char *str, int max_len,
+@@ -127,9 +135,9 @@ static int pretty_print_word(const char
+ len = 0;
+ } else if (len > max_len)
+ ret = len - max_len;
+- do
++ do {
+ fputc(' ', stdout);
+- while (len++ < max_len);
++ } while (len++ < max_len);
+ return ret;
+ }
+
+@@ -142,20 +150,21 @@ static void pretty_print_line(const char
+ static int term_width = -1;
+ int len, w;
+
+- if (term_width < 0)
++ if (term_width < 0) {
+ term_width = get_terminal_width();
+
+- if (term_width > 80) {
+- term_width -= 80;
+- w = term_width / 10;
+- if (w > 8)
+- w = 8;
+- term_width -= 2*w;
+- label_len += w;
+- fs_type_len += w;
+- w = term_width/2;
+- device_len += w;
+- mtpt_len +=w;
++ if (term_width > 80) {
++ term_width -= 80;
++ w = term_width / 10;
++ if (w > 8)
++ w = 8;
++ term_width -= 2*w;
++ label_len += w;
++ fs_type_len += w;
++ w = term_width/2;
++ device_len += w;
++ mtpt_len +=w;
++ }
+ }
+
+ len = pretty_print_word(device, device_len, 0, 1);
+@@ -284,10 +293,7 @@ int main(int argc, char **argv)
+ while ((c = getopt (argc, argv, "c:f:ghlLo:s:t:w:v")) != EOF)
+ switch (c) {
+ case 'c':
+- if (optarg && !*optarg)
+- read = NULL;
+- else
+- read = optarg;
++ read = optarg;
+ if (!write)
+ write = read;
+ break;
+@@ -340,13 +346,11 @@ int main(int argc, char **argv)
+ version = 1;
+ break;
+ case 'w':
+- if (optarg && !*optarg)
+- write = NULL;
+- else
+- write = optarg;
++ write = optarg;
+ break;
+ case 'h':
+ err = 0;
++ /* fallthrough */
+ default:
+ usage(err);
+ }
+--- e2fsprogs-1.42.9.orig/misc/e2image.c
++++ e2fsprogs-1.42.9/misc/e2image.c
+@@ -174,7 +174,7 @@ static void generic_write(int fd, void *
+ printf(_("Writing block %llu\n"), (unsigned long long) block);
+ if (fd != 1)
+ seek_relative(fd, blocksize);
+- return;
++ goto free_and_return;
+ }
+ count = write(fd, buf, blocksize);
+ if (count != blocksize) {
+@@ -191,6 +191,7 @@ static void generic_write(int fd, void *
+
+ exit(1);
+ }
++free_and_return:
+ if (free_buf)
+ ext2fs_free_mem(&buf);
+ }
+@@ -633,7 +634,7 @@ more_blocks:
+ bscount = print_progress(total_written,
+ meta_blocks_count);
+ duration = time(NULL) - start_time;
+- if (duration > 5) {
++ if (duration > 5 && total_written) {
+ time_t est = (duration * meta_blocks_count /
+ total_written) - duration;
+ char buff[30];
+@@ -703,14 +704,15 @@ more_blocks:
+ if (show_progress) {
+ time_t duration = time(NULL) - start_time;
+ char buff[30];
+- while (bscount--)
+- fputc('\b', stderr);
++ fputc('\r', stderr);
+ strftime(buff, 30, "%T", gmtime(&duration));
+- fprintf(stderr, _("\b\b\b\b\b\b\b\bCopied %llu / %llu "
+- "blocks (%d%%) in %s at %.2f MB/s \n"),
+- total_written, meta_blocks_count,
+- calc_percent(total_written, meta_blocks_count), buff,
+- calc_rate(total_written, fs->blocksize, duration));
++ fprintf(stderr, _("Copied %llu / %llu blocks (%d%%) in %s "),
++ total_written, meta_blocks_count,
++ calc_percent(total_written, meta_blocks_count), buff);
++ if (duration)
++ fprintf(stderr, _("at %.2f MB/s"),
++ calc_rate(total_written, fs->blocksize, duration));
++ fputs(" \n", stderr);
+ }
+ #ifdef HAVE_FTRUNCATE64
+ if (sparse) {
+@@ -1410,7 +1412,7 @@ static void install_image(char *device,
+
+ retval = ext2fs_image_inode_read(fs, fd, 0);
+ if (retval) {
+- com_err(image_fn, 0, "while restoring the image table");
++ com_err(image_fn, 0, _("while restoring the image table"));
+ exit(1);
+ }
+
+@@ -1597,7 +1599,7 @@ skip_device:
+ }
+ if (fd != 1) {
+ if (fstat(fd, &st)) {
+- com_err(program_name, 0, "Can not stat output\n");
++ com_err(program_name, 0, _("Can not stat output\n"));
+ exit(1);
+ }
+ if (S_ISBLK(st.st_mode))
+--- e2fsprogs-1.42.9.orig/misc/e4defrag.c
++++ e2fsprogs-1.42.9/misc/e4defrag.c
+@@ -34,7 +34,6 @@
+ #include <unistd.h>
+ #include <ext2fs/ext2_types.h>
+ #include <ext2fs/ext2fs.h>
+-#include <linux/fs.h>
+ #include <sys/ioctl.h>
+ #include <ext2fs/fiemap.h>
+ #include <sys/mman.h>
+@@ -183,29 +182,21 @@ static ext4_fsblk_t files_block_count;
+ static struct frag_statistic_ino frag_rank[SHOW_FRAG_FILES];
+
+
+-/* Local definitions of some syscalls glibc may not yet have */
+-
+-#ifndef HAVE_POSIX_FADVISE
+-#warning Using locally defined posix_fadvise interface.
+-
+-#ifndef __NR_fadvise64_64
+-#error Your kernel headers dont define __NR_fadvise64_64
++/*
++ * We prefer posix_fadvise64 when available, as it allows 64bit offset on
++ * 32bit systems
++ */
++#if defined(HAVE_POSIX_FADVISE64)
++#define posix_fadvise posix_fadvise64
++#elif defined(HAVE_FADVISE64)
++#define posix_fadvise fadvise64
++#elif !defined(HAVE_POSIX_FADVISE)
++#error posix_fadvise not available!
+ #endif
+
+ /*
+- * fadvise() - Give advice about file access.
+- *
+- * @fd: defrag target file's descriptor.
+- * @offset: file offset.
+- * @len: area length.
+- * @advise: process flag.
++ * Local definitions of some syscalls glibc may not yet have
+ */
+-static int posix_fadvise(int fd, loff_t offset, size_t len, int advise)
+-{
+- return syscall(__NR_fadvise64_64, fd, offset, len, advise);
+-}
+-#endif /* ! HAVE_FADVISE64_64 */
+-
+ #ifndef HAVE_SYNC_FILE_RANGE
+ #warning Using locally defined sync_file_range interface.
+
+--- e2fsprogs-1.42.9.orig/misc/ext4.5.in
++++ e2fsprogs-1.42.9/misc/ext4.5.in
+@@ -109,7 +109,6 @@ supported by ext2, ext3, and ext4.
+ This feature enables the storage file type information in directory
+ entries. This feature is supported by ext2, ext3, and ext4.
+ .TP
+-.TP
+ .B flex_bg
+ .br
+ This ext4 feature allows the per-block group metadata (allocation
+@@ -172,6 +171,17 @@ kernels from mounting file systems that
+ .\" .br
+ .\" .B Future feature, available in e2fsprogs 1.43-WIP
+ .TP
++.B sparse_super2
++.br
++This feature indicates that there will only at most two backup
++superblock and block group descriptors. The block groups used to store
++the backup superblock and blockgroup descriptors are stored in the
++superblock, but typically, one will be located at the beginning of block
++group #1, and one in the last block group in the file system. This is
++feature is essentially a more extreme version of sparse_super and is
++designed to allow the a much larger percentage of the disk to have
++contiguous blocks available for data files.
++.TP
+ .B meta_bg
+ .br
+ This ext4 feature allows file systems to be resized on-line without explicitly
+--- /dev/null
++++ e2fsprogs-1.42.9/misc/mk_hugefiles.c
+@@ -0,0 +1,429 @@
++/*
++ * mk_hugefiles.c -- create huge files
++ */
++
++#define _XOPEN_SOURCE 600 /* for inclusion of PATH_MAX in Solaris */
++
++#include "config.h"
++#include <stdio.h>
++#include <string.h>
++#include <strings.h>
++#include <fcntl.h>
++#include <ctype.h>
++#include <time.h>
++#ifdef __linux__
++#include <sys/utsname.h>
++#endif
++#ifdef HAVE_GETOPT_H
++#include <getopt.h>
++#else
++extern char *optarg;
++extern int optind;
++#endif
++#ifdef HAVE_UNISTD_H
++#include <unistd.h>
++#endif
++#ifdef HAVE_STDLIB_H
++#include <stdlib.h>
++#endif
++#ifdef HAVE_ERRNO_H
++#include <errno.h>
++#endif
++#include <sys/ioctl.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <libgen.h>
++#include <limits.h>
++#include <blkid/blkid.h>
++
++#include "ext2fs/ext2_fs.h"
++#include "ext2fs/ext2fsP.h"
++#include "et/com_err.h"
++#include "uuid/uuid.h"
++#include "e2p/e2p.h"
++#include "ext2fs/ext2fs.h"
++#include "util.h"
++#include "profile.h"
++#include "prof_err.h"
++#include "nls-enable.h"
++#include "mke2fs.h"
++
++static int uid;
++static int gid;
++static blk64_t num_blocks;
++static blk64_t num_slack;
++static unsigned long num_files;
++static blk64_t goal;
++static char *fn_prefix;
++static int idx_digits;
++static char *fn_buf;
++static char *fn_numbuf;
++int zero_hugefile = 1;
++
++static errcode_t create_directory(ext2_filsys fs, char *dir,
++ ext2_ino_t *ret_ino)
++
++{
++ struct ext2_inode inode;
++ ext2_ino_t ino = EXT2_ROOT_INO;
++ ext2_ino_t newdir;
++ errcode_t retval = 0;
++ char *fn, *cp, *next;
++
++ fn = malloc(strlen(dir) + 1);
++ if (fn == NULL)
++ return ENOMEM;
++
++ strcpy(fn, dir);
++ cp = fn;
++ while(1) {
++ next = strchr(cp, '/');
++ if (next)
++ *next++ = 0;
++ if (*cp) {
++ retval = ext2fs_new_inode(fs, ino, LINUX_S_IFDIR,
++ NULL, &newdir);
++ if (retval)
++ goto errout;
++
++ retval = ext2fs_mkdir(fs, ino, newdir, cp);
++ if (retval)
++ goto errout;
++
++ ino = newdir;
++ retval = ext2fs_read_inode(fs, ino, &inode);
++ if (retval)
++ goto errout;
++
++ inode.i_uid = uid & 0xFFFF;
++ ext2fs_set_i_uid_high(inode, (uid >> 16) & 0xffff);
++ inode.i_gid = gid & 0xFFFF;
++ ext2fs_set_i_gid_high(inode, (gid >> 16) & 0xffff);
++ retval = ext2fs_write_inode(fs, ino, &inode);
++ if (retval)
++ goto errout;
++ }
++ if (next == NULL || *next == '\0')
++ break;
++ cp = next;
++ }
++errout:
++ free(fn);
++ if (retval == 0)
++ *ret_ino = ino;
++ return retval;
++}
++
++static errcode_t mk_hugefile(ext2_filsys fs, blk64_t num,
++ ext2_ino_t dir, unsigned long idx, ext2_ino_t *ino)
++
++{
++ errcode_t retval;
++ blk64_t lblk, bend;
++ __u64 size;
++ blk64_t left;
++ blk64_t count = 0;
++ struct ext2_inode inode;
++ ext2_extent_handle_t handle;
++
++ retval = ext2fs_new_inode(fs, 0, LINUX_S_IFREG, NULL, ino);
++ if (retval)
++ return retval;
++
++ memset(&inode, 0, sizeof(struct ext2_inode));
++ inode.i_mode = LINUX_S_IFREG | (0666 & ~fs->umask);
++ inode.i_links_count = 1;
++ inode.i_uid = uid & 0xFFFF;
++ ext2fs_set_i_uid_high(inode, (uid >> 16) & 0xffff);
++ inode.i_gid = gid & 0xFFFF;
++ ext2fs_set_i_gid_high(inode, (gid >> 16) & 0xffff);
++
++ retval = ext2fs_write_new_inode(fs, *ino, &inode);
++ if (retval)
++ return retval;
++
++ ext2fs_inode_alloc_stats2(fs, *ino, +1, 0);
++
++ retval = ext2fs_extent_open2(fs, *ino, &inode, &handle);
++ if (retval)
++ return retval;
++
++ lblk = 0;
++ left = num ? num : 1;
++ while (left) {
++ blk64_t pblk, end;
++ blk64_t n = left;
++
++ retval = ext2fs_find_first_zero_block_bitmap2(fs->block_map,
++ goal, ext2fs_blocks_count(fs->super) - 1, &end);
++ if (retval)
++ goto errout;
++ goal = end;
++
++ retval = ext2fs_find_first_set_block_bitmap2(fs->block_map, goal,
++ ext2fs_blocks_count(fs->super) - 1, &bend);
++ if (retval == ENOENT) {
++ bend = ext2fs_blocks_count(fs->super);
++ if (num == 0)
++ left = 0;
++ }
++ if (!num || bend - goal < left)
++ n = bend - goal;
++ pblk = goal;
++ if (num)
++ left -= n;
++ goal += n;
++ count += n;
++ ext2fs_block_alloc_stats_range(fs, pblk, n, +1);
++
++ if (zero_hugefile) {
++ blk64_t ret_blk;
++ retval = ext2fs_zero_blocks2(fs, pblk, n,
++ &ret_blk, NULL);
++
++ if (retval)
++ com_err(program_name, retval,
++ _("while zeroing block %llu "
++ "for hugefile"), ret_blk);
++ }
++
++ while (n) {
++ blk64_t l = n;
++ struct ext2fs_extent newextent;
++
++ if (l > EXT_INIT_MAX_LEN)
++ l = EXT_INIT_MAX_LEN;
++
++ newextent.e_len = l;
++ newextent.e_pblk = pblk;
++ newextent.e_lblk = lblk;
++ newextent.e_flags = 0;
++
++ retval = ext2fs_extent_insert(handle,
++ EXT2_EXTENT_INSERT_AFTER, &newextent);
++ if (retval)
++ return retval;
++ pblk += l;
++ lblk += l;
++ n -= l;
++ }
++ }
++
++ retval = ext2fs_read_inode(fs, *ino, &inode);
++ if (retval)
++ goto errout;
++
++ retval = ext2fs_iblk_add_blocks(fs, &inode,
++ count / EXT2FS_CLUSTER_RATIO(fs));
++ if (retval)
++ goto errout;
++ size = (__u64) count * fs->blocksize;
++ inode.i_size = size & 0xffffffff;
++ inode.i_size_high = (size >> 32);
++
++ retval = ext2fs_write_new_inode(fs, *ino, &inode);
++ if (retval)
++ goto errout;
++
++ if (idx_digits)
++ sprintf(fn_numbuf, "%0*lu", idx_digits, idx);
++ else if (num_files > 1)
++ sprintf(fn_numbuf, "%lu", idx);
++
++retry:
++ retval = ext2fs_link(fs, dir, fn_buf, *ino, EXT2_FT_REG_FILE);
++ if (retval == EXT2_ET_DIR_NO_SPACE) {
++ retval = ext2fs_expand_dir(fs, dir);
++ if (retval)
++ goto errout;
++ goto retry;
++ }
++
++ if (retval)
++ goto errout;
++
++errout:
++ if (handle)
++ ext2fs_extent_free(handle);
++
++ return retval;
++}
++
++static blk64_t calc_overhead(ext2_filsys fs, blk64_t num)
++{
++ blk64_t e_blocks, e_blocks2, e_blocks3, e_blocks4;
++ int extents_per_block;
++ int extents = (num + EXT_INIT_MAX_LEN - 1) / EXT_INIT_MAX_LEN;
++
++ if (extents <= 4)
++ return 0;
++
++ /*
++ * This calculation is due to the fact that we are inefficient
++ * in how handle extent splits when appending to the end of
++ * the extent tree. Sigh. We should fix this so that we can
++ * actually store 340 extents per 4k block, instead of only 170.
++ */
++ extents_per_block = ((fs->blocksize -
++ sizeof(struct ext3_extent_header)) /
++ sizeof(struct ext3_extent));
++ extents_per_block = (extents_per_block/ 2) - 1;
++
++ e_blocks = (extents + extents_per_block - 1) / extents_per_block;
++ e_blocks2 = (e_blocks + extents_per_block - 1) / extents_per_block;
++ e_blocks3 = (e_blocks2 + extents_per_block - 1) / extents_per_block;
++ e_blocks4 = (e_blocks3 + extents_per_block - 1) / extents_per_block;
++ return e_blocks + e_blocks2 + e_blocks3 + e_blocks4;
++}
++
++/*
++ * Find the place where we should start allocating blocks for the huge
++ * files. Leave <slack> free blocks at the beginning of the file
++ * system for things like metadata blocks.
++ */
++static blk64_t get_start_block(ext2_filsys fs, blk64_t slack)
++{
++ errcode_t retval;
++ blk64_t blk = fs->super->s_first_data_block, next;
++ blk64_t last_blk = ext2fs_blocks_count(fs->super) - 1;
++
++ while (slack) {
++ retval = ext2fs_find_first_zero_block_bitmap2(fs->block_map,
++ blk, last_blk, &blk);
++ if (retval)
++ break;
++
++ retval = ext2fs_find_first_set_block_bitmap2(fs->block_map,
++ blk, last_blk, &next);
++ if (retval)
++ next = last_blk;
++ next--;
++
++ if (next - blk > slack) {
++ blk += slack;
++ break;
++ }
++
++ slack -= (next - blk);
++ blk = next;
++ }
++ return blk;
++}
++
++static blk64_t round_up_align(blk64_t b, unsigned long align)
++{
++ unsigned long m;
++
++ if (align == 0)
++ return b;
++ m = b % align;
++ if (m)
++ b += align - m;
++ return b;
++}
++
++errcode_t mk_hugefiles(ext2_filsys fs)
++{
++ unsigned long i;
++ ext2_ino_t dir;
++ errcode_t retval;
++ blk64_t fs_blocks;
++ unsigned long align;
++ int d, dsize;
++ char *t;
++
++ if (!get_bool_from_profile(fs_types, "make_hugefiles", 0))
++ return 0;
++
++ uid = get_int_from_profile(fs_types, "hugefiles_uid", 0);
++ gid = get_int_from_profile(fs_types, "hugefiles_gid", 0);
++ fs->umask = get_int_from_profile(fs_types, "hugefiles_umask", 077);
++ num_files = get_int_from_profile(fs_types, "num_hugefiles", 0);
++ t = get_string_from_profile(fs_types, "hugefiles_slack", "1M");
++ num_slack = parse_num_blocks2(t, fs->super->s_log_block_size);
++ free(t);
++ t = get_string_from_profile(fs_types, "hugefiles_size", "0");
++ num_blocks = parse_num_blocks2(t, fs->super->s_log_block_size);
++ free(t);
++ t = get_string_from_profile(fs_types, "hugefiles_align", "0");
++ align = parse_num_blocks2(t, fs->super->s_log_block_size);
++ free(t);
++ num_blocks = round_up_align(num_blocks, align);
++ zero_hugefile = get_int_from_profile(fs_types, "zero_hugefiles",
++ zero_hugefile);
++
++ t = get_string_from_profile(fs_types, "hugefiles_dir", "/");
++ retval = create_directory(fs, t, &dir);
++ free(t);
++ if (retval)
++ return retval;
++
++ fn_prefix = get_string_from_profile(fs_types, "hugefiles_name",
++ "hugefile");
++ idx_digits = get_int_from_profile(fs_types, "hugefiles_digits", 5);
++ d = int_log10(num_files) + 1;
++ if (idx_digits > d)
++ d = idx_digits;
++ dsize = strlen(fn_prefix) + d + 16;
++ fn_buf = malloc(dsize);
++ if (!fn_buf) {
++ free(fn_prefix);
++ return ENOMEM;
++ }
++ strcpy(fn_buf, fn_prefix);
++ fn_numbuf = fn_buf + strlen(fn_prefix);
++ free(fn_prefix);
++
++ fs_blocks = ext2fs_free_blocks_count(fs->super);
++ if (fs_blocks < num_slack + align)
++ return ENOMEM;
++ fs_blocks -= num_slack + align;
++ if (num_blocks && num_blocks > fs_blocks)
++ return ENOMEM;
++ if (num_blocks == 0 && num_files == 0)
++ num_files = 1;
++
++ if (num_files == 0 && num_blocks) {
++ num_files = fs_blocks / num_blocks;
++ fs_blocks -= (num_files / 16) + 1;
++ fs_blocks -= calc_overhead(fs, num_blocks) * num_files;
++ num_files = fs_blocks / num_blocks;
++ }
++
++ if (num_blocks == 0 && num_files > 1) {
++ num_blocks = fs_blocks / num_files;
++ fs_blocks -= (num_files / 16) + 1;
++ fs_blocks -= calc_overhead(fs, num_blocks) * num_files;
++ num_blocks = fs_blocks / num_files;
++ }
++
++ num_slack += calc_overhead(fs, num_blocks) * num_files;
++ num_slack += (num_files / 16) + 1; /* space for dir entries */
++ goal = get_start_block(fs, num_slack);
++ goal = round_up_align(goal, align);
++
++ if (!quiet) {
++ if (zero_hugefile && verbose)
++ printf(_("Huge files will be zero'ed\n"));
++ printf(_("Creating %lu huge file(s) "), num_files);
++ if (num_blocks)
++ printf(_("with %llu blocks each"), num_blocks);
++ fputs(": ", stdout);
++ }
++ for (i=0; i < num_files; i++) {
++ ext2_ino_t ino;
++
++ retval = mk_hugefile(fs, num_blocks, dir, i, &ino);
++ if (retval) {
++ com_err(program_name, retval,
++ _("while creating huge file %lu"), i);
++ goto errout;
++ }
++ }
++ if (!quiet)
++ fputs(_("done\n"), stdout);
++
++errout:
++ free(fn_buf);
++ return retval;
++}
+--- e2fsprogs-1.42.9.orig/misc/mke2fs.8.in
++++ e2fsprogs-1.42.9/misc/mke2fs.8.in
+@@ -64,7 +64,7 @@ mke2fs \- create an ext2/ext3/ext4 files
+ ]
+ [
+ .B \-O
+-.IR feature [,...]
++[^]\fIfeature\fR[,...]
+ ]
+ [
+ .B \-q
+@@ -246,6 +246,10 @@ parity disk, so N will be the number of
+ This allows the block allocator to prevent read-modify-write of the
+ parity in a RAID stripe if possible when the data is written.
+ .TP
++.BI offset= offset
++Create the filesystem at an offset from the beginning of the device or
++file. This can be useful when creating disk images for virtual machines.
++.TP
+ .BI resize= max-online-resize
+ Reserve enough space so that the block group descriptor table can grow
+ to support a filesystem that has
+@@ -270,6 +274,22 @@ small risk if the system crashes before
+ entirely one time. If the option value is omitted, it defaults to 1 to
+ enable lazy journal inode zeroing.
+ .TP
++.BI num_backup_sb= <0|1|2>
++If the
++.B sparse_super2
++file system feature is enabled this option controls whether there will
++be 0, 1, or 2 backup superblocks created in the file system.
++.TP
++.B packed_meta_blocks\fR[\fB= \fI<0 to disable, 1 to enable>\fR]
++Place the allocation bitmaps and the inode table at the beginning of the
++disk. This option requires that the flex_bg file system feature to be
++enabled in order for it to have effect, and will also create the journal
++at the beginning of the file system. This option is useful for flash
++devices that use SLC flash at the beginning of the disk.
++It also maximizes the range of contiguous data blocks, which
++can be useful for certain specialized use cases, such as supported
++Shingled Drives.
++.TP
+ .BI root_owner [=uid:gid]
+ Specify the numeric user and group ID of the root directory. If no UID:GID
+ is specified, use the user and group ID of the user running \fBmke2fs\fR.
+@@ -405,6 +425,13 @@ The size of the journal must be at least
+ (i.e., 1MB if using 1k blocks, 4MB if using 4k blocks, etc.)
+ and may be no more than 10,240,000 filesystem blocks or half the total
+ file system size (whichever is smaller)
++.TP
++.BI location =journal-location
++Specify the location of the journal. The argument
++.I journal-location
++can either be specified as a block number, or if the number has a units
++suffix (e.g., 'M', 'G', etc.) interpret it as the offset from the
++beginning of the file system.
+ @JDEV@.TP
+ @JDEV@.BI device= external-journal
+ @JDEV@Attach the filesystem to the journal block device located on
+@@ -508,7 +535,7 @@ filesystem. The creator field is set by
+ .B mke2fs
+ executable was compiled for.
+ .TP
+-.B "\-O \fIfeature\fR[,...]"
++.B "\-O \fR[^]\fIfeature\fR[,...]"
+ Create a filesystem with the given features (filesystem options),
+ overriding the default filesystem options. The features that are
+ enabled by default are specified by the
+@@ -544,7 +571,7 @@ section of the configuration file.
+ .sp
+ The filesystem feature set is comprised of a list of features, separated
+ by commas, that are to be enabled. To disable a feature, simply
+-prefix the feature name with a caret ('^') or a minus ('-') character.
++prefix the feature name with a caret ('^') character.
+ Features with dependencies will not be removed successfully.
+ The pseudo-filesystem feature "none" will clear all filesystem features.
+ .TP
+--- e2fsprogs-1.42.9.orig/misc/mke2fs.c
++++ e2fsprogs-1.42.9/misc/mke2fs.c
+@@ -62,6 +62,7 @@ extern int optind;
+ #include "../version.h"
+ #include "nls-enable.h"
+ #include "quota/mkquota.h"
++#include "mke2fs.h"
+
+ #define STRIDE_LENGTH 8
+
+@@ -76,26 +77,30 @@ extern int optind;
+ extern int isatty(int);
+ extern FILE *fpopen(const char *cmd, const char *mode);
+
+-static const char * program_name = "mke2fs";
++const char * program_name = "mke2fs";
+ static const char * device_name /* = NULL */;
+
+ /* Command line options */
+ static int cflag;
+-static int verbose;
+-static int quiet;
++int verbose;
++int quiet;
+ static int super_only;
+ static int discard = 1; /* attempt to discard device before fs creation */
+ static int direct_io;
+ static int force;
+ static int noaction;
++static int num_backups = 2; /* number of backup bg's for sparse_super2 */
+ static uid_t root_uid;
+ static gid_t root_gid;
+ int journal_size;
+ int journal_flags;
+ static int lazy_itable_init;
++static int packed_meta_blocks;
+ static char *bad_blocks_filename = NULL;
+ static __u32 fs_stride;
+ static int quotatype = -1; /* Initialize both user and group quotas by default */
++static __u64 offset;
++static blk64_t journal_location = ~0LL;
+
+ static struct ext2_super_block fs_param;
+ static char *fs_uuid = NULL;
+@@ -104,7 +109,7 @@ static char *volume_label;
+ static char *mount_dir;
+ char *journal_device;
+ static int sync_kludge; /* Set using the MKE2FS_SYNC env. option */
+-static char **fs_types;
++char **fs_types;
+
+ static profile_t profile;
+
+@@ -139,7 +144,7 @@ static int int_log2(unsigned long long a
+ return l;
+ }
+
+-static int int_log10(unsigned long long arg)
++int int_log10(unsigned long long arg)
+ {
+ int l;
+
+@@ -308,6 +313,40 @@ _("Warning: the backup superblock/group
+ ext2fs_badblocks_list_iterate_end(bb_iter);
+ }
+
++static errcode_t packed_allocate_tables(ext2_filsys fs)
++{
++ errcode_t retval;
++ dgrp_t i;
++ blk64_t goal = 0;
++
++ for (i = 0; i < fs->group_desc_count; i++) {
++ retval = ext2fs_new_block2(fs, goal, NULL, &goal);
++ if (retval)
++ return retval;
++ ext2fs_block_alloc_stats2(fs, goal, +1);
++ ext2fs_block_bitmap_loc_set(fs, i, goal);
++ }
++ for (i = 0; i < fs->group_desc_count; i++) {
++ retval = ext2fs_new_block2(fs, goal, NULL, &goal);
++ if (retval)
++ return retval;
++ ext2fs_block_alloc_stats2(fs, goal, +1);
++ ext2fs_inode_bitmap_loc_set(fs, i, goal);
++ }
++ for (i = 0; i < fs->group_desc_count; i++) {
++ blk64_t end = ext2fs_blocks_count(fs->super) - 1;
++ retval = ext2fs_get_free_blocks2(fs, goal, end,
++ fs->inode_blocks_per_group,
++ fs->block_map, &goal);
++ if (retval)
++ return retval;
++ ext2fs_block_alloc_stats_range(fs, goal,
++ fs->inode_blocks_per_group, +1);
++ ext2fs_inode_table_loc_set(fs, i, goal);
++ }
++ return 0;
++}
++
+ static void write_inode_tables(ext2_filsys fs, int lazy_flag, int itable_zeroed)
+ {
+ errcode_t retval;
+@@ -710,6 +749,19 @@ static void parse_extended_opts(struct e
+ continue;
+ }
+ param->s_desc_size = desc_size;
++ } else if (strcmp(token, "offset") == 0) {
++ if (!arg) {
++ r_usage++;
++ badopt = token;
++ continue;
++ }
++ offset = strtoull(arg, &p, 0);
++ if (*p) {
++ fprintf(stderr, _("Invalid offset: %s\n"),
++ arg);
++ r_usage++;
++ continue;
++ }
+ } else if (strcmp(token, "mmp_update_interval") == 0) {
+ if (!arg) {
+ r_usage++;
+@@ -724,6 +776,28 @@ static void parse_extended_opts(struct e
+ r_usage++;
+ continue;
+ }
++ } else if (strcmp(token, "num_backup_sb") == 0) {
++ if (!arg) {
++ r_usage++;
++ badopt = token;
++ continue;
++ }
++ num_backups = strtoul(arg, &p, 0);
++ if (*p || num_backups > 2) {
++ fprintf(stderr,
++ _("Invalid # of backup "
++ "superbocks: %s\n"),
++ arg);
++ r_usage++;
++ continue;
++ }
++ } else if (strcmp(token, "packed_meta_blocks") == 0) {
++ if (arg)
++ packed_meta_blocks = strtoul(arg, &p, 0);
++ else
++ packed_meta_blocks = 1;
++ if (packed_meta_blocks)
++ journal_location = 0;
+ } else if (strcmp(token, "stride") == 0) {
+ if (!arg) {
+ r_usage++;
+@@ -879,9 +953,13 @@ static void parse_extended_opts(struct e
+ "and may take an argument which\n"
+ "\tis set off by an equals ('=') sign.\n\n"
+ "Valid extended options are:\n"
++ "\tmmp_update_interval=<interval>\n"
++ "\tnum_backup_sb=<0|1|2>\n"
+ "\tstride=<RAID per-disk data chunk in blocks>\n"
+ "\tstripe-width=<RAID stride * data disks in blocks>\n"
++ "\toffset=<offset to create the file system>\n"
+ "\tresize=<resize maximum size in blocks>\n"
++ "\tpacked_meta_blocks=<0 to disable, 1 to enable>\n"
+ "\tlazy_itable_init=<0 to disable, 1 to enable>\n"
+ "\tlazy_journal_init=<0 to disable, 1 to enable>\n"
+ "\troot_uid=<uid of root directory>\n"
+@@ -908,7 +986,8 @@ static __u32 ok_features[3] = {
+ EXT3_FEATURE_COMPAT_HAS_JOURNAL |
+ EXT2_FEATURE_COMPAT_RESIZE_INODE |
+ EXT2_FEATURE_COMPAT_DIR_INDEX |
+- EXT2_FEATURE_COMPAT_EXT_ATTR,
++ EXT2_FEATURE_COMPAT_EXT_ATTR |
++ EXT4_FEATURE_COMPAT_SPARSE_SUPER2,
+ /* Incompat */
+ EXT2_FEATURE_INCOMPAT_FILETYPE|
+ EXT3_FEATURE_INCOMPAT_EXTENTS|
+@@ -1165,7 +1244,7 @@ static char **parse_fs_type(const char *
+ return (list.list);
+ }
+
+-static char *get_string_from_profile(char **types, const char *opt,
++char *get_string_from_profile(char **types, const char *opt,
+ const char *def_val)
+ {
+ char *ret = 0;
+@@ -1182,7 +1261,7 @@ static char *get_string_from_profile(cha
+ return (ret);
+ }
+
+-static int get_int_from_profile(char **types, const char *opt, int def_val)
++int get_int_from_profile(char **types, const char *opt, int def_val)
+ {
+ int ret;
+ char **cpp;
+@@ -1205,7 +1284,7 @@ static double get_double_from_profile(ch
+ return ret;
+ }
+
+-static int get_bool_from_profile(char **types, const char *opt, int def_val)
++int get_bool_from_profile(char **types, const char *opt, int def_val)
+ {
+ int ret;
+ char **cpp;
+@@ -1958,6 +2037,8 @@ profile_error:
+ }
+ #endif
+
++ num_backups = get_int_from_profile(fs_types, "num_backup_sb", 2);
++
+ blocksize = EXT2_BLOCK_SIZE(&fs_param);
+
+ /*
+@@ -1994,6 +2075,20 @@ profile_error:
+ EXT2_MKJOURNAL_LAZYINIT : 0;
+ journal_flags |= EXT2_MKJOURNAL_NO_MNT_CHECK;
+
++ if (!journal_location_string)
++ journal_location_string = get_string_from_profile(fs_types,
++ "journal_location", "");
++ if ((journal_location == ~0ULL) && journal_location_string &&
++ *journal_location_string)
++ journal_location = parse_num_blocks2(journal_location_string,
++ fs_param.s_log_block_size);
++ free(journal_location_string);
++
++ packed_meta_blocks = get_bool_from_profile(fs_types,
++ "packed_meta_blocks", 0);
++ if (packed_meta_blocks)
++ journal_location = 0;
++
+ /* Get options from profile */
+ for (cpp = fs_types; *cpp; cpp++) {
+ tmp = NULL;
+@@ -2145,6 +2240,13 @@ profile_error:
+ ext2fs_r_blocks_count_set(&fs_param, reserved_ratio *
+ ext2fs_blocks_count(&fs_param) / 100.0);
+
++ if (fs_param.s_feature_compat & EXT4_FEATURE_COMPAT_SPARSE_SUPER2) {
++ if (num_backups >= 1)
++ fs_param.s_backup_bgs[0] = 1;
++ if (num_backups >= 2)
++ fs_param.s_backup_bgs[1] = ~0;
++ }
++
+ free(fs_type);
+ free(usage_types);
+ }
+@@ -2238,11 +2340,9 @@ static int mke2fs_setup_tdb(const char *
+ sprintf(tdb_file, "%s/mke2fs-%s.e2undo", tdb_dir, dev_name);
+ free(tmp_name);
+
+- if (!access(tdb_file, F_OK)) {
+- if (unlink(tdb_file) < 0) {
+- retval = errno;
+- goto errout;
+- }
++ if ((unlink(tdb_file) < 0) && (errno != ENOENT)) {
++ retval = errno;
++ goto errout;
+ }
+
+ set_undo_io_backing_manager(*io_ptr);
+@@ -2318,30 +2418,43 @@ static int mke2fs_discard_device(ext2_fi
+
+ static void fix_cluster_bg_counts(ext2_filsys fs)
+ {
+- blk64_t cluster, num_clusters, tot_free;
+- unsigned num = 0;
+- int grp_free, num_free, group;
+-
+- num_clusters = EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super));
+- tot_free = num_free = group = grp_free = 0;
+- for (cluster = EXT2FS_B2C(fs, fs->super->s_first_data_block);
+- cluster < num_clusters; cluster++) {
+- if (!ext2fs_test_block_bitmap2(fs->block_map,
+- EXT2FS_C2B(fs, cluster))) {
+- grp_free++;
+- tot_free++;
+- }
+- num++;
+- if ((num == fs->super->s_clusters_per_group) ||
+- (cluster == num_clusters-1)) {
++ blk64_t block, num_blocks, last_block, next;
++ blk64_t tot_free = 0;
++ errcode_t retval;
++ dgrp_t group = 0;
++ int grp_free = 0;
++
++ num_blocks = ext2fs_blocks_count(fs->super);
++ last_block = ext2fs_group_last_block2(fs, group);
++ block = fs->super->s_first_data_block;
++ while (block < num_blocks) {
++ retval = ext2fs_find_first_zero_block_bitmap2(fs->block_map,
++ block, last_block, &next);
++ if (retval == 0)
++ block = next;
++ else {
++ block = last_block + 1;
++ goto next_bg;
++ }
++
++ retval = ext2fs_find_first_set_block_bitmap2(fs->block_map,
++ block, last_block, &next);
++ if (retval)
++ next = last_block + 1;
++ grp_free += EXT2FS_NUM_B2C(fs, next - block);
++ tot_free += next - block;
++ block = next;
++
++ if (block > last_block) {
++ next_bg:
+ ext2fs_bg_free_blocks_count_set(fs, group, grp_free);
+ ext2fs_group_desc_csum_set(fs, group);
+- num = 0;
+ grp_free = 0;
+ group++;
++ last_block = ext2fs_group_last_block2(fs, group);
+ }
+ }
+- ext2fs_free_blocks_count_set(fs->super, EXT2FS_C2B(fs, tot_free));
++ ext2fs_free_blocks_count_set(fs->super, tot_free);
+ }
+
+ static int create_quota_inodes(ext2_filsys fs)
+@@ -2368,7 +2481,7 @@ int main (int argc, char *argv[])
+ int flags;
+ int old_bitmaps;
+ io_manager io_ptr;
+- char tdb_string[40];
++ char opt_string[40];
+ char *hash_alg_str;
+ int itable_zeroed = 0;
+
+@@ -2435,12 +2548,17 @@ int main (int argc, char *argv[])
+ "0s - skipping inode table wipe\n"));
+ lazy_itable_init = 1;
+ itable_zeroed = 1;
++ zero_hugefile = 0;
+ }
+ }
+
+- sprintf(tdb_string, "tdb_data_size=%d", fs->blocksize <= 4096 ?
++ sprintf(opt_string, "tdb_data_size=%d", fs->blocksize <= 4096 ?
+ 32768 : fs->blocksize * 8);
+- io_channel_set_options(fs->io, tdb_string);
++ io_channel_set_options(fs->io, opt_string);
++ if (offset) {
++ sprintf(opt_string, "offset=%llu", offset);
++ io_channel_set_options(fs->io, opt_string);
++ }
+
+ if (fs_param.s_flags & EXT2_FLAGS_TEST_FILESYS)
+ fs->super->s_flags |= EXT2_FLAGS_TEST_FILESYS;
+@@ -2562,12 +2680,16 @@ int main (int argc, char *argv[])
+ read_bb_file(fs, &bb_list, bad_blocks_filename);
+ if (cflag)
+ test_disk(fs, &bb_list);
+-
+ handle_bad_blocks(fs, bb_list);
++
+ fs->stride = fs_stride = fs->super->s_raid_stride;
+ if (!quiet)
+ printf("%s", _("Allocating group tables: "));
+- retval = ext2fs_allocate_tables(fs);
++ if ((fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) &&
++ packed_meta_blocks)
++ retval = packed_allocate_tables(fs);
++ else
++ retval = ext2fs_allocate_tables(fs);
+ if (retval) {
+ com_err(program_name, retval, "%s",
+ _("while trying to allocate filesystem tables"));
+@@ -2693,8 +2815,9 @@ int main (int argc, char *argv[])
+ journal_blocks);
+ fflush(stdout);
+ }
+- retval = ext2fs_add_journal_inode(fs, journal_blocks,
+- journal_flags);
++ retval = ext2fs_add_journal_inode2(fs, journal_blocks,
++ journal_location,
++ journal_flags);
+ if (retval) {
+ com_err(program_name, retval, "%s",
+ _("\n\twhile trying to create journal"));
+@@ -2726,6 +2849,10 @@ no_journal:
+ EXT4_FEATURE_RO_COMPAT_QUOTA))
+ create_quota_inodes(fs);
+
++ retval = mk_hugefiles(fs);
++ if (retval)
++ com_err(program_name, retval, "while creating huge files");
++
+ if (!quiet)
+ printf("%s", _("Writing superblocks and "
+ "filesystem accounting information: "));
+--- e2fsprogs-1.42.9.orig/misc/mke2fs.conf.5.in
++++ e2fsprogs-1.42.9/misc/mke2fs.conf.5.in
+@@ -357,6 +357,18 @@ initialization noticeably, but it requir
+ initializing the filesystem in the background when the filesystem is
+ first mounted.
+ .TP
++.I journal_location
++This relation specifies the location of the journal.
++.TP
++.I num_backup_sb
++This relation indicates whether file systems with the
++.B sparse_super2
++feature enabled should be created with 0, 1, or 2 backup superblocks.
++.TP
++.I packed_meta_blocks
++This boolean relation specifes whether the allocation bitmaps, inode
++table, and journal should be located at the beginning of the file system.
++.TP
+ .I inode_ratio
+ This relation specifies the default inode ratio if the user does not
+ specify one on the command line.
+@@ -408,6 +420,71 @@ system feature is enabled. It can be ov
+ .B \-C
+ command line option to
+ .BR mke2fs (8)
++.TP
++.I make_hugefiles
++This boolean relation enables the creation of pre-allocated files as
++part of formatting the file system.
++.TP
++.I hugefiles_uid
++This relation controls the user ownership for all of the files and
++directories created by the
++.I make_hugefiles
++feature.
++.TP
++.I hugefiles_gid
++This relation controls the group ownership for all of the files and
++directories created by the
++.I make_hugefiles
++feature.
++.TP
++.I hugefiles_umask
++This relation specifies the umask used when creating the files and
++directories by the
++.I make_hugefiles
++feature.
++.TP
++.I num_hugefiles
++This relation specifies the number of huge files to be created. If this
++relation is not specified, or is set to zero, and the
++.I hugefiles_size
++relation is non-zero, then
++.I make_hugefiles
++will create as many huge files as can fit to fill the entire file system.
++.TP
++.I hugefiles_slack
++This relation specifies how much space should be reserved for other
++files.
++.TP
++.I hugefiles_size
++This relation specifies the size of the huge files. If this relation is
++not specified, the default is to fill the entire file system.
++.TP
++.I hugefiles_align
++This relation specifies the alignment for the start block of the huge
++files. It also forces the size of huge files to be a multiple of the
++requested alignment. If this relation is not specified, no alignment
++requirement will be imposed on the huge files.
++.TP
++.I hugefiles_name
++This relation specifies the base file name for the huge files.
++.TP
++.I hugefiles_digits
++This relation specifies the (zero-padded) width of the field for the
++huge file number.
++.TP
++.I zero_hugefiles
++This boolean relation specifies whether or not zero blocks will be
++written to the hugefiles while
++.BR mke2fs(8)
++is creating them. By default, zero blocks will be written to the huge
++files to avoid stale data from being made available to potentially
++untrusted user programs, unless the device supports a discard/trim
++operation which will take care of zeroing the device blocks. By
++.I zero_hugefiles
++to false, this step will always be skipped, which can be useful if it is
++known that the disk has been previously erased, or if the user programs
++that will have access to the huge files are trusted to not reveal stale
++data.
+ .SH THE [devices] STANZA
+ Each tag in the
+ .I [devices]
+--- /dev/null
++++ e2fsprogs-1.42.9/misc/mke2fs.h
+@@ -0,0 +1,30 @@
++/*
++ * mke2fs.h
++ *
++ * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
++ * 2003, 2004, 2005 by Theodore Ts'o.
++ *
++ * %Begin-Header%
++ * This file may be redistributed under the terms of the GNU Public
++ * License.
++ * %End-Header%
++ */
++
++/* mke2fs.c */
++extern const char * program_name;
++extern int quiet;
++extern int verbose;
++extern int zero_hugefile;
++extern char **fs_types;
++
++extern char *get_string_from_profile(char **types, const char *opt,
++ const char *def_val);
++extern int get_int_from_profile(char **types, const char *opt, int def_val);
++extern int get_bool_from_profile(char **types, const char *opt, int def_val);
++extern int int_log10(unsigned long long arg);
++
++/* mk_hugefiles.c */
++extern errcode_t mk_hugefiles(ext2_filsys fs);
++
++
++
+--- e2fsprogs-1.42.9.orig/misc/tune2fs.8.in
++++ e2fsprogs-1.42.9/misc/tune2fs.8.in
+@@ -333,6 +333,13 @@ megabytes. The size of the journal mus
+ and may be no more than 102,400 filesystem blocks.
+ There must be enough free space in the filesystem to create a journal of
+ that size.
++.TP
++.BI location =journal-location
++Specify the location of the journal. The argument
++.I journal-location
++can either be specified as a block number, or if the number has a units
++suffix (e.g., 'M', 'G', etc.) interpret it as the offset from the
++beginning of the file system.
+ @JDEV@.TP
+ @JDEV@.BI device= external-journal
+ @JDEV@Attach the filesystem to the journal block device located on
+--- e2fsprogs-1.42.9.orig/misc/tune2fs.c
++++ e2fsprogs-1.42.9/misc/tune2fs.c
+@@ -98,6 +98,7 @@ static int usrquota, grpquota;
+
+ int journal_size, journal_flags;
+ char *journal_device;
++static blk64_t journal_location = ~0LL;
+
+ static struct list_head blk_move_list;
+
+@@ -694,8 +695,13 @@ static int add_journal(ext2_filsys fs)
+ fflush(stdout);
+ journal_blocks = figure_journal_size(journal_size, fs);
+
+- retval = ext2fs_add_journal_inode(fs, journal_blocks,
+- journal_flags);
++ if (journal_location_string)
++ journal_location =
++ parse_num_blocks2(journal_location_string,
++ fs->super->s_log_block_size);
++ retval = ext2fs_add_journal_inode2(fs, journal_blocks,
++ journal_location,
++ journal_flags);
+ if (retval) {
+ fprintf(stderr, "\n");
+ com_err(program_name, retval, "%s",
+@@ -1856,15 +1862,12 @@ static int tune2fs_setup_tdb(const char
+ goto alloc_fn_fail;
+ sprintf(tdb_file, "%s/tune2fs-%s.e2undo", tdb_dir, dev_name);
+
+- if (!access(tdb_file, F_OK)) {
+- if (unlink(tdb_file) < 0) {
+- retval = errno;
+- com_err(program_name, retval,
+- _("while trying to delete %s"),
+- tdb_file);
+- free(tdb_file);
+- return retval;
+- }
++ if ((unlink(tdb_file) < 0) && (errno != ENOENT)) {
++ retval = errno;
++ com_err(program_name, retval,
++ _("while trying to delete %s"), tdb_file);
++ free(tdb_file);
++ return retval;
+ }
+
+ set_undo_io_backing_manager(*io_ptr);
+--- e2fsprogs-1.42.9.orig/misc/util.c
++++ e2fsprogs-1.42.9/misc/util.c
+@@ -34,6 +34,8 @@
+ #include "blkid/blkid.h"
+ #include "util.h"
+
++char *journal_location_string = NULL;
++
+ #ifndef HAVE_STRCASECMP
+ int strcasecmp (char *s1, char *s2)
+ {
+@@ -218,6 +220,12 @@ void parse_journal_opts(const char *opts
+ journal_size = strtoul(arg, &p, 0);
+ if (*p)
+ journal_usage++;
++ } else if (!strcmp(token, "location")) {
++ if (!arg) {
++ journal_usage++;
++ continue;
++ }
++ journal_location_string = strdup(arg);
+ } else if (strcmp(token, "v1_superblock") == 0) {
+ journal_flags |= EXT2_MKJOURNAL_V1_SUPER;
+ continue;
+@@ -231,7 +239,8 @@ void parse_journal_opts(const char *opts
+ "\tis set off by an equals ('=') sign.\n\n"
+ "Valid journal options are:\n"
+ "\tsize=<journal size in megabytes>\n"
+- "\tdevice=<journal device>\n\n"
++ "\tdevice=<journal device>\n"
++ "\tlocation=<journal location>\n\n"
+ "The journal size must be between "
+ "1024 and 10240000 filesystem blocks.\n\n"), stderr);
+ free(buf);
+--- e2fsprogs-1.42.9.orig/misc/util.h
++++ e2fsprogs-1.42.9/misc/util.h
+@@ -13,6 +13,7 @@
+ extern int journal_size;
+ extern int journal_flags;
+ extern char *journal_device;
++extern char *journal_location_string;
+
+ #ifndef HAVE_STRCASECMP
+ extern int strcasecmp (char *s1, char *s2);
+--- e2fsprogs-1.42.9.orig/resize/Makefile.in
++++ e2fsprogs-1.42.9/resize/Makefile.in
+@@ -28,11 +28,11 @@ SRCS= $(srcdir)/extent.c \
+ $(srcdir)/resource_track.c \
+ $(srcdir)/sim_progress.c
+
+-LIBS= $(LIBE2P) $(LIBEXT2FS) $(LIBCOM_ERR) $(LIBINTL)
++LIBS= $(LIBE2P) $(LIBEXT2FS) $(LIBCOM_ERR) $(LIBINTL) $(SYSLIBS)
+ DEPLIBS= $(LIBE2P) $(LIBEXT2FS) $(DEPLIBCOM_ERR)
+
+ STATIC_LIBS= $(STATIC_LIBE2P) $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR) \
+- $(LIBINTL)
++ $(LIBINTL) $(SYSLIBS)
+ DEPSTATIC_LIBS= $(STATIC_LIBE2P) $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR)
+
+ .c.o:
+--- e2fsprogs-1.42.9.orig/resize/online.c
++++ e2fsprogs-1.42.9/resize/online.c
+@@ -76,6 +76,14 @@ errcode_t online_resize_fs(ext2_filsys f
+ no_resize_ioctl = 1;
+ }
+
++ if (EXT2_HAS_COMPAT_FEATURE(fs->super,
++ EXT4_FEATURE_COMPAT_SPARSE_SUPER2) &&
++ (access("/sys/fs/ext4/features/sparse_super2", R_OK) != 0)) {
++ com_err(program_name, 0, _("kernel does not support online "
++ "resize with sparse_super2"));
++ exit(1);
++ }
++
+ printf(_("Filesystem at %s is mounted on %s; "
+ "on-line resizing required\n"), fs->device_name, mtpt);
+
+--- e2fsprogs-1.42.9.orig/resize/resize2fs.c
++++ e2fsprogs-1.42.9/resize/resize2fs.c
+@@ -53,6 +53,9 @@ static errcode_t ext2fs_calculate_summar
+ static errcode_t fix_sb_journal_backup(ext2_filsys fs);
+ static errcode_t mark_table_blocks(ext2_filsys fs,
+ ext2fs_block_bitmap bmap);
++static errcode_t clear_sparse_super2_last_group(ext2_resize_t rfs);
++static errcode_t reserve_sparse_super2_last_group(ext2_resize_t rfs,
++ ext2fs_block_bitmap meta_bmap);
+
+ /*
+ * Some helper CPP macros
+@@ -191,6 +194,10 @@ errcode_t resize_fs(ext2_filsys fs, blk6
+ goto errout;
+ print_resource_track(rfs, &rtrack, fs->io);
+
++ retval = clear_sparse_super2_last_group(rfs);
++ if (retval)
++ goto errout;
++
+ rfs->new_fs->super->s_state &= ~EXT2_ERROR_FS;
+ rfs->new_fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
+
+@@ -460,6 +467,33 @@ retry:
+ }
+
+ /*
++ * Update the location of the backup superblocks if the
++ * sparse_super2 feature is enabled.
++ */
++ if (fs->super->s_feature_compat & EXT4_FEATURE_COMPAT_SPARSE_SUPER2) {
++ dgrp_t last_bg = fs->group_desc_count - 1;
++ dgrp_t old_last_bg = old_fs->group_desc_count - 1;
++
++ if (last_bg > old_last_bg) {
++ if (old_fs->group_desc_count == 1)
++ fs->super->s_backup_bgs[0] = 1;
++ if (old_fs->group_desc_count == 1 &&
++ fs->super->s_backup_bgs[0])
++ fs->super->s_backup_bgs[0] = last_bg;
++ else if (fs->super->s_backup_bgs[1])
++ fs->super->s_backup_bgs[1] = last_bg;
++ } else if (last_bg < old_last_bg) {
++ if (fs->super->s_backup_bgs[0] > last_bg)
++ fs->super->s_backup_bgs[0] = 0;
++ if (fs->super->s_backup_bgs[1] > last_bg)
++ fs->super->s_backup_bgs[1] = 0;
++ if (last_bg > 1 &&
++ old_fs->super->s_backup_bgs[1] == old_last_bg)
++ fs->super->s_backup_bgs[1] = last_bg;
++ }
++ }
++
++ /*
+ * If we are shrinking the number of block groups, we're done
+ * and can exit now.
+ */
+@@ -615,14 +649,13 @@ errout:
+ */
+ static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
+ {
+- ext2_filsys fs;
++ ext2_filsys fs = rfs->new_fs;
+ int adj = 0;
+ errcode_t retval;
+ blk64_t group_block;
+ unsigned long i;
+ unsigned long max_group;
+
+- fs = rfs->new_fs;
+ ext2fs_mark_super_dirty(fs);
+ ext2fs_mark_bb_dirty(fs);
+ ext2fs_mark_ib_dirty(fs);
+@@ -952,6 +985,10 @@ static errcode_t blocks_to_move(ext2_res
+ new_blocks = fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
+ }
+
++ retval = reserve_sparse_super2_last_group(rfs, meta_bmap);
++ if (retval)
++ goto errout;
++
+ if (old_blocks == new_blocks) {
+ retval = 0;
+ goto errout;
+@@ -1840,6 +1877,147 @@ errout:
+ }
+
+ /*
++ * This function is used when expanding a file system. It frees the
++ * superblock and block group descriptor blocks from the block group
++ * which is no longer the last block group.
++ */
++static errcode_t clear_sparse_super2_last_group(ext2_resize_t rfs)
++{
++ ext2_filsys fs = rfs->new_fs;
++ ext2_filsys old_fs = rfs->old_fs;
++ errcode_t retval;
++ dgrp_t old_last_bg = rfs->old_fs->group_desc_count - 1;
++ dgrp_t last_bg = fs->group_desc_count - 1;
++ blk64_t sb, old_desc;
++ blk_t num;
++
++ if (!(fs->super->s_feature_compat & EXT4_FEATURE_COMPAT_SPARSE_SUPER2))
++ return 0;
++
++ if (last_bg <= old_last_bg)
++ return 0;
++
++ if (fs->super->s_backup_bgs[0] == old_fs->super->s_backup_bgs[0] &&
++ fs->super->s_backup_bgs[1] == old_fs->super->s_backup_bgs[1])
++ return 0;
++
++ if (old_fs->super->s_backup_bgs[0] != old_last_bg &&
++ old_fs->super->s_backup_bgs[1] != old_last_bg)
++ return 0;
++
++ if (fs->super->s_backup_bgs[0] == old_last_bg ||
++ fs->super->s_backup_bgs[1] == old_last_bg)
++ return 0;
++
++ retval = ext2fs_super_and_bgd_loc2(rfs->old_fs, old_last_bg,
++ &sb, &old_desc, NULL, &num);
++ if (retval)
++ return retval;
++
++ if (sb)
++ ext2fs_unmark_block_bitmap2(fs->block_map, sb);
++ if (old_desc)
++ ext2fs_unmark_block_bitmap_range2(fs->block_map, old_desc, num);
++ return 0;
++}
++
++/*
++ * This function is used when shrinking a file system. We need to
++ * utilize blocks from what will be the new last block group for the
++ * backup superblock and block group descriptor blocks.
++ * Unfortunately, those blocks may be used by other files or fs
++ * metadata blocks. We need to mark them as being in use.
++ */
++static errcode_t reserve_sparse_super2_last_group(ext2_resize_t rfs,
++ ext2fs_block_bitmap meta_bmap)
++{
++ ext2_filsys fs = rfs->new_fs;
++ ext2_filsys old_fs = rfs->old_fs;
++ errcode_t retval;
++ dgrp_t old_last_bg = rfs->old_fs->group_desc_count - 1;
++ dgrp_t last_bg = fs->group_desc_count - 1;
++ dgrp_t g;
++ blk64_t blk, sb, old_desc;
++ blk_t i, num;
++ int realloc = 0;
++
++ if (!(fs->super->s_feature_compat & EXT4_FEATURE_COMPAT_SPARSE_SUPER2))
++ return 0;
++
++ if (last_bg >= old_last_bg)
++ return 0;
++
++ if (fs->super->s_backup_bgs[0] == old_fs->super->s_backup_bgs[0] &&
++ fs->super->s_backup_bgs[1] == old_fs->super->s_backup_bgs[1])
++ return 0;
++
++ if (fs->super->s_backup_bgs[0] != last_bg &&
++ fs->super->s_backup_bgs[1] != last_bg)
++ return 0;
++
++ if (old_fs->super->s_backup_bgs[0] == last_bg ||
++ old_fs->super->s_backup_bgs[1] == last_bg)
++ return 0;
++
++ retval = ext2fs_super_and_bgd_loc2(rfs->new_fs, last_bg,
++ &sb, &old_desc, NULL, &num);
++ if (retval)
++ return retval;
++
++ if (!sb) {
++ fputs(_("Should never happen! No sb in last super_sparse bg?\n"),
++ stderr);
++ exit(1);
++ }
++ if (old_desc != sb+1) {
++ fputs(_("Should never happen! Unexpected old_desc in "
++ "super_sparse bg?\n"),
++ stderr);
++ exit(1);
++ }
++ num = (old_desc) ? num : 1;
++
++ /* Reserve the backup blocks */
++ ext2fs_mark_block_bitmap_range2(fs->block_map, sb, num);
++
++ for (g = 0; g < fs->group_desc_count; g++) {
++ blk64_t mb;
++
++ mb = ext2fs_block_bitmap_loc(fs, g);
++ if ((mb >= sb) && (mb < sb + num)) {
++ ext2fs_block_bitmap_loc_set(fs, g, 0);
++ realloc = 1;
++ }
++ mb = ext2fs_inode_bitmap_loc(fs, g);
++ if ((mb >= sb) && (mb < sb + num)) {
++ ext2fs_inode_bitmap_loc_set(fs, g, 0);
++ realloc = 1;
++ }
++ mb = ext2fs_inode_table_loc(fs, g);
++ if ((mb < sb + num) &&
++ (sb < mb + fs->inode_blocks_per_group)) {
++ ext2fs_inode_table_loc_set(fs, g, 0);
++ realloc = 1;
++ }
++ if (realloc) {
++ retval = ext2fs_allocate_group_table(fs, g, 0);
++ if (retval)
++ return retval;
++ }
++ }
++
++ for (blk = sb, i = 0; i < num; blk++, i++) {
++ if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
++ !ext2fs_test_block_bitmap2(meta_bmap, blk)) {
++ ext2fs_mark_block_bitmap2(rfs->move_blocks, blk);
++ rfs->needed_blocks++;
++ }
++ ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk);
++ }
++ return 0;
++}
++
++/*
+ * Fix the resize inode
+ */
+ static errcode_t fix_resize_inode(ext2_filsys fs)
+--- e2fsprogs-1.42.9.orig/resize/test_extent.c
++++ e2fsprogs-1.42.9/resize/test_extent.c
+@@ -109,6 +109,8 @@ void do_test(FILE *in, FILE *out)
+ } else
+ fputs("# Syntax error\n", out);
+ }
++ if (extent)
++ ext2fs_free_extent_table(extent);
+ }
+
+ #ifdef __GNUC__
+--- e2fsprogs-1.42.9.orig/tests/d_special_files/script
++++ e2fsprogs-1.42.9/tests/d_special_files/script
+@@ -18,7 +18,7 @@ status=$?
+ echo Exit status is $status >> $OUT
+
+ $DEBUGFS -w $TMPFILE << EOF > /dev/null 2>&1
+-set_current_time 201301151400
++set_current_time 20130115140000
+ set_super_value lastcheck 0
+ set_super_value hash_seed null
+ set_super_value mkfs_time 0
+--- e2fsprogs-1.42.9.orig/tests/f_crashdisk/expect.1
++++ e2fsprogs-1.42.9/tests/f_crashdisk/expect.1
+@@ -2,10 +2,12 @@ ext2fs_open2: The ext2 superblock is cor
+ ../e2fsck/e2fsck: Superblock invalid, trying backup blocks...
+ ../e2fsck/e2fsck: The ext2 superblock is corrupt while trying to open test.img
+
+-The superblock could not be read or does not describe a correct ext2
+-filesystem. If the device is valid and it really contains an ext2
++The superblock could not be read or does not describe a valid ext2/ext3/ext4
++filesystem. If the device is valid and it really contains an ext2/ext3/ext4
+ filesystem (and not swap or ufs or something else), then the superblock
+ is corrupt, and you might try running e2fsck with an alternate superblock:
+ e2fsck -b 8193 <device>
++ or
++ e2fsck -b 32768 <device>
+
+ Exit status is 8
+--- e2fsprogs-1.42.9.orig/tests/f_dup4/script
++++ e2fsprogs-1.42.9/tests/f_dup4/script
+@@ -8,7 +8,7 @@ echo "/ Murphy Magic. The SeCrEt of the
+ touch $TMPFILE
+ $MKE2FS -N 32 -F -o Linux -b 1024 $TMPFILE 100 > /dev/null 2>&1
+ $DEBUGFS -w $TMPFILE << EOF > /dev/null 2>&1
+-set_current_time 200704102100
++set_current_time 20070410210000
+ set_super_value lastcheck 0
+ set_super_value hash_seed null
+ set_super_value mkfs_time 0
+--- e2fsprogs-1.42.9.orig/tests/f_dup_resize/script
++++ e2fsprogs-1.42.9/tests/f_dup_resize/script
+@@ -11,8 +11,8 @@ $DEBUGFS -w $TMPFILE << EOF > /dev/null
+ freeb 4 4
+ freeb 8195 4
+ write $TEST_DATA debugfs
+-set_current_time 200504110000
+-set_inode_field debugfs mtime 200504110000
++set_current_time 20050411000000
++set_inode_field debugfs mtime 2005041100000000
+ q
+ EOF
+
+--- e2fsprogs-1.42.9.orig/tests/m_bigjournal/expect.1
++++ e2fsprogs-1.42.9/tests/m_bigjournal/expect.1
+@@ -55,7 +55,7 @@ Group 0: (Blocks 0-32767)
+ 31836 free blocks, 5 free inodes, 2 directories, 5 unused inodes
+ Free blocks: 764-1184, 1269-1696, 1781-32767
+ Free inodes: 12-16
+-Group 1: (Blocks 32768-65535) [INODE_UNINIT]
++Group 1: (Blocks 32768-65535) [INODE_UNINIT, BLOCK_UNINIT]
+ Backup superblock at 32768, Group descriptors at 32769-32769
+ Reserved GDT blocks at 32770-33440
+ Block bitmap at 674 (bg #0 + 674), Inode bitmap at 1186 (bg #0 + 1186)
+@@ -69,7 +69,7 @@ Group 2: (Blocks 65536-98303) [INODE_UNI
+ 32768 free blocks, 16 free inodes, 0 directories, 16 unused inodes
+ Free blocks: 65536-98303
+ Free inodes: 33-48
+-Group 3: (Blocks 98304-131071) [INODE_UNINIT]
++Group 3: (Blocks 98304-131071) [INODE_UNINIT, BLOCK_UNINIT]
+ Backup superblock at 98304, Group descriptors at 98305-98305
+ Reserved GDT blocks at 98306-98976
+ Block bitmap at 676 (bg #0 + 676), Inode bitmap at 1188 (bg #0 + 1188)
+@@ -83,7 +83,7 @@ Group 4: (Blocks 131072-163839) [INODE_U
+ 32768 free blocks, 16 free inodes, 0 directories, 16 unused inodes
+ Free blocks: 131072-163839
+ Free inodes: 65-80
+-Group 5: (Blocks 163840-196607) [INODE_UNINIT]
++Group 5: (Blocks 163840-196607) [INODE_UNINIT, BLOCK_UNINIT]
+ Backup superblock at 163840, Group descriptors at 163841-163841
+ Reserved GDT blocks at 163842-164512
+ Block bitmap at 678 (bg #0 + 678), Inode bitmap at 1190 (bg #0 + 1190)
+@@ -97,7 +97,7 @@ Group 6: (Blocks 196608-229375) [INODE_U
+ 32768 free blocks, 16 free inodes, 0 directories, 16 unused inodes
+ Free blocks: 196608-229375
+ Free inodes: 97-112
+-Group 7: (Blocks 229376-262143) [INODE_UNINIT]
++Group 7: (Blocks 229376-262143) [INODE_UNINIT, BLOCK_UNINIT]
+ Backup superblock at 229376, Group descriptors at 229377-229377
+ Reserved GDT blocks at 229378-230048
+ Block bitmap at 680 (bg #0 + 680), Inode bitmap at 1192 (bg #0 + 1192)
+@@ -111,7 +111,7 @@ Group 8: (Blocks 262144-294911) [INODE_U
+ 32768 free blocks, 16 free inodes, 0 directories, 16 unused inodes
+ Free blocks: 262144-294911
+ Free inodes: 129-144
+-Group 9: (Blocks 294912-327679) [INODE_UNINIT]
++Group 9: (Blocks 294912-327679) [INODE_UNINIT, BLOCK_UNINIT]
+ Backup superblock at 294912, Group descriptors at 294913-294913
+ Reserved GDT blocks at 294914-295584
+ Block bitmap at 682 (bg #0 + 682), Inode bitmap at 1194 (bg #0 + 1194)
+@@ -209,7 +209,7 @@ Group 24: (Blocks 786432-819199) [INODE_
+ 32768 free blocks, 16 free inodes, 0 directories, 16 unused inodes
+ Free blocks: 786432-819199
+ Free inodes: 385-400
+-Group 25: (Blocks 819200-851967) [INODE_UNINIT]
++Group 25: (Blocks 819200-851967) [INODE_UNINIT, BLOCK_UNINIT]
+ Backup superblock at 819200, Group descriptors at 819201-819201
+ Reserved GDT blocks at 819202-819872
+ Block bitmap at 698 (bg #0 + 698), Inode bitmap at 1210 (bg #0 + 1210)
+@@ -223,7 +223,7 @@ Group 26: (Blocks 851968-884735) [INODE_
+ 32768 free blocks, 16 free inodes, 0 directories, 16 unused inodes
+ Free blocks: 851968-884735
+ Free inodes: 417-432
+-Group 27: (Blocks 884736-917503) [INODE_UNINIT]
++Group 27: (Blocks 884736-917503) [INODE_UNINIT, BLOCK_UNINIT]
+ Backup superblock at 884736, Group descriptors at 884737-884737
+ Reserved GDT blocks at 884738-885408
+ Block bitmap at 700 (bg #0 + 700), Inode bitmap at 1212 (bg #0 + 1212)
+@@ -551,7 +551,7 @@ Group 80: (Blocks 2621440-2654207) [INOD
+ 32768 free blocks, 16 free inodes, 0 directories, 16 unused inodes
+ Free blocks: 2621440-2654207
+ Free inodes: 1281-1296
+-Group 81: (Blocks 2654208-2686975) [INODE_UNINIT]
++Group 81: (Blocks 2654208-2686975) [INODE_UNINIT, BLOCK_UNINIT]
+ Backup superblock at 2654208, Group descriptors at 2654209-2654209
+ Reserved GDT blocks at 2654210-2654880
+ Block bitmap at 754 (bg #0 + 754), Inode bitmap at 1266 (bg #0 + 1266)
+--- e2fsprogs-1.42.9.orig/tests/m_uninit/expect.1
++++ e2fsprogs-1.42.9/tests/m_uninit/expect.1
+@@ -64,7 +64,7 @@ Group 0: (Blocks 1-8192) [ITABLE_ZEROED]
+ 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]
++Group 1: (Blocks 8193-16384) [INODE_UNINIT, BLOCK_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)
+@@ -76,9 +76,9 @@ Group 2: (Blocks 16385-24576) [INODE_UNI
+ 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: 16385-24576
++ Free blocks: 16643-24576
+ Free inodes: 4097-6144
+-Group 3: (Blocks 24577-32768) [INODE_UNINIT, ITABLE_ZEROED]
++Group 3: (Blocks 24577-32768) [INODE_UNINIT, BLOCK_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)
+@@ -90,9 +90,9 @@ Group 4: (Blocks 32769-40960) [INODE_UNI
+ 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: 32769-40960
++ Free blocks: 33027-40960
+ Free inodes: 8193-10240
+-Group 5: (Blocks 40961-49152) [INODE_UNINIT, ITABLE_ZEROED]
++Group 5: (Blocks 40961-49152) [INODE_UNINIT, BLOCK_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)
+@@ -104,9 +104,9 @@ Group 6: (Blocks 49153-57344) [INODE_UNI
+ 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: 49153-57344
++ Free blocks: 49411-57344
+ Free inodes: 12289-14336
+-Group 7: (Blocks 57345-65536) [INODE_UNINIT, ITABLE_ZEROED]
++Group 7: (Blocks 57345-65536) [INODE_UNINIT, BLOCK_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)
+@@ -118,9 +118,9 @@ Group 8: (Blocks 65537-73728) [INODE_UNI
+ 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: 65537-73728
++ Free blocks: 65795-73728
+ Free inodes: 16385-18432
+-Group 9: (Blocks 73729-81920) [INODE_UNINIT, ITABLE_ZEROED]
++Group 9: (Blocks 73729-81920) [INODE_UNINIT, BLOCK_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)
+@@ -132,31 +132,31 @@ Group 10: (Blocks 81921-90112) [INODE_UN
+ 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: 81921-90112
++ Free blocks: 82179-90112
+ Free inodes: 20481-22528
+ 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: 90113-98304
++ Free blocks: 90371-98304
+ Free inodes: 22529-24576
+ 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: 98305-106496
++ Free blocks: 98563-106496
+ Free inodes: 24577-26624
+ 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: 106497-114688
++ Free blocks: 106755-114688
+ Free inodes: 26625-28672
+ 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: 114689-122880
++ Free blocks: 114947-122880
+ Free inodes: 28673-30720
+ Group 15: (Blocks 122881-131071) [INODE_UNINIT, ITABLE_ZEROED]
+ Block bitmap at 122881 (+0), Inode bitmap at 122882 (+1)
+--- e2fsprogs-1.42.9.orig/tests/progs/Makefile.in
++++ e2fsprogs-1.42.9/tests/progs/Makefile.in
+@@ -21,7 +21,7 @@ TEST_ICOUNT_OBJS= test_icount.o test_ico
+
+ SRCS= $(srcdir)/test_rel.c
+
+-LIBS= $(LIBEXT2FS) $(LIBSS) $(LIBCOM_ERR)
++LIBS= $(LIBEXT2FS) $(LIBSS) $(LIBCOM_ERR) $(SYSLIBS)
+ DEPLIBS= $(LIBEXT2FS) $(DEPLIBSS) $(DEPLIBCOM_ERR)
+
+ .c.o:
+--- e2fsprogs-1.42.9.orig/util/Makefile.in
++++ e2fsprogs-1.42.9/util/Makefile.in
+@@ -22,6 +22,12 @@ PROGS= subst symlinks
+
+ all:: $(PROGS) gen-tarball
+
++dirpaths.h:
++ $(E) " CREATE dirpaths.h"
++ $(Q) echo "/* fake dirpaths.h for config.h */" > dirpaths.h
++
++subst.o: dirpaths.h
++
+ subst: subst.o
+ $(E) " LD $@"
+ $(Q) $(BUILD_CC) $(BUILD_LDFLAGS) -o subst subst.o
+@@ -46,7 +52,7 @@ tarballs: gen-tarball
+
+ clean:
+ $(RM) -f $(PROGS) \#* *.s *.o *.a *~ core *.tar.gz gen-tarball \
+- copy-sparse
++ copy-sparse dirpaths.h
+
+ mostlyclean: clean
+
+@@ -58,4 +64,4 @@ distclean: clean
+ # Makefile dependencies follow. This must be the last section in
+ # the Makefile.in file
+ #
+-subst.o: $(srcdir)/subst.c
++subst.o: $(srcdir)/subst.c $(top_builddir)/lib/config.h dirpaths.h
+--- e2fsprogs-1.42.9.orig/util/subst.c
++++ e2fsprogs-1.42.9/util/subst.c
+@@ -5,6 +5,7 @@
+ *
+ */
+
++#include "config.h"
+ #include <stdio.h>
+ #include <errno.h>
+ #include <stdlib.h>
+@@ -13,6 +14,7 @@
+ #include <ctype.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
++#include <fcntl.h>
+ #include <time.h>
+ #include <utime.h>
+
+@@ -264,21 +266,11 @@ static void parse_config_file(FILE *f)
+ /*
+ * Return 0 if the files are different, 1 if the files are the same.
+ */
+-static int compare_file(const char *outfn, const char *newfn)
++static int compare_file(FILE *old_f, FILE *new_f)
+ {
+- FILE *old_f, *new_f;
+ char oldbuf[2048], newbuf[2048], *oldcp, *newcp;
+ int retval;
+
+- old_f = fopen(outfn, "r");
+- if (!old_f)
+- return 0;
+- new_f = fopen(newfn, "r");
+- if (!new_f) {
+- fclose(old_f);
+- return 0;
+- }
+-
+ while (1) {
+ oldcp = fgets(oldbuf, sizeof(oldbuf), old_f);
+ newcp = fgets(newbuf, sizeof(newbuf), new_f);
+@@ -291,8 +283,6 @@ static int compare_file(const char *outf
+ break;
+ }
+ }
+- fclose(old_f);
+- fclose(new_f);
+ return retval;
+ }
+
+@@ -302,12 +292,14 @@ int main(int argc, char **argv)
+ {
+ char line[2048];
+ int c;
+- FILE *in, *out;
++ int fd;
++ FILE *in, *out, *old = NULL;
+ char *outfn = NULL, *newfn = NULL;
+ int verbose = 0;
+ int adjust_timestamp = 0;
++ int got_atime = 0;
+ struct stat stbuf;
+- struct utimbuf ut;
++ struct timeval tv[2];
+
+ while ((c = getopt (argc, argv, "f:tv")) != EOF) {
+ switch (c) {
+@@ -351,11 +343,34 @@ int main(int argc, char **argv)
+ }
+ strcpy(newfn, outfn);
+ strcat(newfn, ".new");
+- out = fopen(newfn, "w");
+- if (!out) {
++ fd = open(newfn, O_CREAT|O_TRUNC|O_RDWR, 0444);
++ if (fd < 0) {
+ perror(newfn);
+ exit(1);
+ }
++ out = fdopen(fd, "w+");
++ if (!out) {
++ perror("fdopen");
++ exit(1);
++ }
++
++ fd = open(outfn, O_RDONLY);
++ if (fd > 0) {
++ /* save the original atime, if possible */
++ if (fstat(fd, &stbuf) == 0) {
++#if HAVE_STRUCT_STAT_ST_ATIM
++ tv[0].tv_sec = stbuf.st_atim.tv_sec;
++ tv[0].tv_usec = stbuf.st_atim.tv_nsec / 1000;
++#else
++ tv[0].tv_sec = stbuf.st_atime;
++ tv[0].tv_usec = 0;
++#endif
++ got_atime = 1;
++ }
++ old = fdopen(fd, "r");
++ if (!old)
++ close(fd);
++ }
+ } else {
+ out = stdout;
+ outfn = 0;
+@@ -368,32 +383,49 @@ int main(int argc, char **argv)
+ fputs(line, out);
+ }
+ fclose(in);
+- fclose(out);
+ if (outfn) {
+- struct stat st;
+- if (compare_file(outfn, newfn)) {
++ fflush(out);
++ rewind(out);
++ if (old && compare_file(old, out)) {
+ if (verbose)
+ printf("No change, keeping %s.\n", outfn);
+ if (adjust_timestamp) {
+- if (stat(outfn, &stbuf) == 0) {
+- if (verbose)
+- printf("Updating modtime for %s\n", outfn);
+- ut.actime = stbuf.st_atime;
+- ut.modtime = time(0);
+- if (utime(outfn, &ut) < 0)
+- perror("utime");
++ if (verbose)
++ printf("Updating modtime for %s\n", outfn);
++ if (gettimeofday(&tv[1], NULL) < 0) {
++ perror("gettimeofday");
++ exit(1);
+ }
++ if (got_atime == 0)
++ tv[0] = tv[1];
++ else if (verbose)
++ printf("Using original atime\n");
++#ifdef HAVE_FUTIMES
++ if (futimes(fileno(old), tv) < 0)
++ perror("futimes");
++#else
++ if (utimes(outfn, tv) < 0)
++ perror("utimes");
++#endif
+ }
+- unlink(newfn);
++ fclose(out);
++ if (unlink(newfn) < 0)
++ perror("unlink");
+ } else {
+ if (verbose)
+ printf("Creating or replacing %s.\n", outfn);
+- rename(newfn, outfn);
++ fclose(out);
++ if (old)
++ fclose(old);
++ old = NULL;
++ if (rename(newfn, outfn) < 0) {
++ perror("rename");
++ exit(1);
++ }
+ }
+- /* set read-only to alert user it is a generated file */
+- if (stat(outfn, &st) == 0)
+- chmod(outfn, st.st_mode & ~0222);
+ }
++ if (old)
++ fclose(old);
+ return (0);
+ }
+
+--- e2fsprogs-1.42.9.orig/version.h
++++ e2fsprogs-1.42.9/version.h
+@@ -8,4 +8,4 @@
+ */
+
+ #define E2FSPROGS_VERSION "1.42.9"
+-#define E2FSPROGS_DATE "28-Dec-2013"
++#define E2FSPROGS_DATE "4-Feb-2014"