--- Begin Message ---
Package: dump
Version: 0.4b47-4+~tjw12r5
Severity: normal
Dear Maintainer,
Dump cannot handle more than 2^32 blocks. This was reported upstream
some years ago along with a patch that I am including here.
I'm reporting this as I have another ext4 patch that I've built on top
of this one.
I've also attached a testcase that doesn't require >12TB of data to
reproduce (it needs about 3GB of available disk space)
It's crafted to my setup and will require modification for anybody else
to use.
-- System Information:
Debian Release: 12.7
APT prefers stable-security
APT policy: (500, 'stable-security'), (500, 'stable')
Architecture: amd64 (x86_64)
Kernel: Linux 6.1.0-25-amd64 (SMP w/4 CPU threads; PREEMPT)
Kernel taint flags: TAINT_WARN
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: sysvinit (via /sbin/init)
Versions of packages dump depends on:
ii libblkid1 2.38.1-5+deb12u1
ii libbz2-1.0 1.0.8-5+b1
ii libc6 2.36-9+deb12u8
ii libcom-err2 1.47.0-2
ii libext2fs2 1.47.0-2
ii liblzo2-2 2.10-2
ii libreadline8 8.2-1.3
ii libselinux1 3.4-1+b6
ii tar 1.34+dfsg-1.2+deb12u1
ii zlib1g 1:1.2.13.dfsg-1
dump recommends no packages.
dump suggests no packages.
-- no debconf information
diff -urN dump-0.4b47.orig/dump/dump.h dump-0.4b47/dump/dump.h
--- dump-0.4b47.orig/dump/dump.h 2022-05-03 10:02:27.000000000 +0000
+++ dump-0.4b47/dump/dump.h 2022-05-03 10:02:27.000000000 +0000
@@ -140,8 +140,8 @@
int mapdirs (dump_ino_t maxino, long long *tapesize);
/* file dumping routines */
-void blksout (blk_t *blkp, int frags, dump_ino_t ino);
-void bread (ext2_loff_t blkno, char *buf, int size);
+void blksout (blk64_t *blkp, int frags, dump_ino_t ino);
+void bread (ext2_loff_t blkno, char *buf, size_t size);
void dumpino (struct dinode *dp, dump_ino_t ino, int metaonly);
#ifdef __linux__
void dumpdirino (struct dinode *dp, dump_ino_t ino);
@@ -153,7 +153,7 @@
/* tape writing routines */
int alloctape (void);
void close_rewind (void);
-void dumpblock (blk_t blkno, int size);
+void dumpblock (blk64_t blkno, int size);
void startnewtape (int top);
time_t trewind (void);
void writerec (const void *dp, int isspcl);
diff -urN dump-0.4b47.orig/dump/tape.c dump-0.4b47/dump/tape.c
--- dump-0.4b47.orig/dump/tape.c 2022-05-03 10:02:27.000000000 +0000
+++ dump-0.4b47/dump/tape.c 2022-05-03 10:02:27.000000000 +0000
@@ -254,7 +254,7 @@
}
void
-dumpblock(blk_t blkno, int size)
+dumpblock(blk64_t blkno, int size)
{
int avail, tpblks;
ext2_loff_t dblkno;
diff -urN dump-0.4b47.orig/dump/traverse.c dump-0.4b47/dump/traverse.c
--- dump-0.4b47.orig/dump/traverse.c 2021-01-01 16:28:57.000000000 +0000
+++ dump-0.4b47/dump/traverse.c 2021-01-01 16:28:57.000000000 +0000
@@ -748,7 +748,7 @@
struct block_context {
ext2_ino_t ino;
- blk_t *buf;
+ blk64_t *buf;
int cnt;
int max;
int next_block;
@@ -758,8 +758,8 @@
* Dump a block to the tape
*/
static int
-dumponeblock(UNUSED(ext2_filsys fs), blk_t *blocknr, e2_blkcnt_t blockcnt,
- UNUSED(blk_t ref_block), UNUSED(int ref_offset), void * private)
+dumponeblock(UNUSED(ext2_filsys fs), blk64_t *blocknr, e2_blkcnt_t blockcnt,
+ UNUSED(blk64_t ref_block), UNUSED(int ref_offset), void * private)
{
struct block_context *p;
e2_blkcnt_t i;
@@ -840,7 +840,7 @@
spcl.c_dinode.di_size = sblock->fs_bsize;
spcl.c_flags |= DR_EXTATTRIBUTES;
spcl.c_extattributes = EXT_XATTR;
- blksout(&dp->di_file_acl, EXT2_FRAGS_PER_BLOCK(fs->super), ino);
+ blksout((blk64_t *)&dp->di_file_acl,
EXT2_FRAGS_PER_BLOCK(fs->super), ino);
spcl.c_flags &= ~DR_EXTATTRIBUTES;
spcl.c_extattributes = 0;
}
@@ -978,12 +978,12 @@
}
#ifdef __linux__
bc.max = NINDIR(sblock) * EXT2_FRAGS_PER_BLOCK(fs->super);
- bc.buf = malloc (bc.max * sizeof (int));
+ bc.buf = malloc (bc.max * sizeof (blk64_t));
bc.cnt = 0;
bc.ino = ino;
bc.next_block = 0;
- ext2fs_block_iterate2(fs, (ext2_ino_t)ino, BLOCK_FLAG_DATA_ONLY, NULL,
dumponeblock, (void *)&bc);
+ ext2fs_block_iterate3(fs, (ext2_ino_t)ino, BLOCK_FLAG_DATA_ONLY, NULL,
dumponeblock, (void *)&bc);
/* deal with holes at the end of the inode */
if (i_size > ((uint64_t)bc.next_block) * sblock->fs_fsize) {
remaining = i_size - ((uint64_t)bc.next_block) *
sblock->fs_fsize;
@@ -1261,9 +1261,9 @@
* Collect up the data into tape record sized buffers and output them.
*/
void
-blksout(blk_t *blkp, int frags, dump_ino_t ino)
+blksout(blk64_t *blkp, int frags, dump_ino_t ino)
{
- blk_t *bp;
+ blk64_t *bp;
int i, j, count, blks, tbperdb;
blks = howmany(frags * sblock->fs_fsize, TP_BSIZE);
@@ -1394,7 +1394,7 @@
int breaderrors = 0;
void
-bread(ext2_loff_t blkno, char *buf, int size)
+bread(ext2_loff_t blkno, char *buf, size_t size)
{
int cnt, i;
#!/bin/bash
set -Eeuo pipefail
homedir=$( readlink -f $( dirname $0 ) )
cd $homedir
rm -f d1
rm -f d2
rm -fr d1.mnt
rm -fr d2.mnt
rm -fr mnt
rm -fr restore
cleanup() {
umount $homedir/mnt >&/dev/null || true
vgchange -an vg30T >&/dev/null || true
[[ -z ${ld3} ]] || losetup -d ${ld3} >&/dev/null || true
[[ -z ${ld2} ]] || losetup -d ${ld2} >&/dev/null || true
umount $homedir/d1.mnt >&/dev/null || true
umount $homedir/d2.mnt >&/dev/null || true
[[ -z ${ld1} ]] || losetup -d ${ld1} >&/dev/null || true
[[ -z ${ld0} ]] || losetup -d ${ld0} >&/dev/null || true
rm -f $homedir/d1
rm -f $homedir/d2
rm -fr $homedir/d1.mnt
rm -fr $homedir/d2.mnt
rm -fr $homedir/mnt
rm -fr $homedir/restore
}
trap cleanup EXIT
tfdfr=0
tfdbr=0
tbdfr=0
tbdbr=0
cfdfr=0
cfdbr=0
cbdfr=0
cbdbr=0
mkdir -p mnt
truncate -s 3G d1
ld0=$( losetup -f )
losetup ${ld0} d1
mkfs.ext4 ${ld0} >&/dev/null
mkdir -p d1.mnt
mount ${ld0} d1.mnt
truncate -s 1G d2
ld1=$( losetup -f )
losetup ${ld1} d2
mkfs.ext4 ${ld1} >&/dev/null
mkdir -p d2.mnt
mount ${ld1} d2.mnt
truncate -s 15T d1.mnt/pv
truncate -s 15T d2.mnt/pv
ld2=$( losetup -f )
losetup ${ld2} d1.mnt/pv
ld3=$( losetup -f )
losetup ${ld3} d2.mnt/pv
vgcreate vg30T ${ld2} ${ld3} >&/dev/null
lvcreate -n big -l 7860000 vg30T >&/dev/null
mkfs.ext4 /dev/vg30T/big >&/dev/null
mount /dev/vg30T/big mnt
echo "fallocate bigfile1 - this is slow"
fallocate -l 10T mnt/bigfile1
echo "fallocate bigfile2 - this is slow"
fallocate -l 10T mnt/bigfile2
dd if=/dev/urandom of=mnt/bigblock bs=1K count=10K >&/dev/null
echo "Removing bigfiles - this is slow"
rm mnt/bigfile1 mnt/bigfile2
sync
umount mnt
mount -o ro /dev/vg30T/big mnt
#debugfs -R "stat bigblock" /dev/vg30T/big | cat
#debugfs -R "stat bigblock" /dev/vg30T/big | tail -n 1
#debugfs -R "stat bigblock" /dev/vg30T/big | tail -n 1 | sed 's/.*-//'
extent=$( debugfs -R "stat bigblock" /dev/vg30T/big 2>/dev/null | tail -n 1 |
sed 's/.*-//' )
if [[ $extent -le 4294967295 ]]; then
echo "bigblock does not extend to an extent >= 2^32. Test needs fixing"
exit 1
fi
test_pipe() {
$1 -q -0 $3 -f - 2>/dev/null | $2 -C -D mnt/ -f - >&/dev/null
}
test_file() {
rm -fr restore
mkdir -p restore
cd restore
$1 -q -0 $3 -f - 2>/dev/null | $2 -r -f - >&/dev/null || return 1
rm restoresymtable
cd ..
diff -q -ur --no-dereference mnt/ restore/ >&/dev/null || return 1
}
dumpdev=/dev/vg30T/big
echo
echo "Testing fixed dump, fixed restore compare"
test_pipe dump restore $dumpdev || cfdfr=1
echo
echo "Testing fixed dump, bookworm restore compare"
test_pipe dump restore.orig $dumpdev || cfdbr=1
echo
echo "Testing bookworm dump, fixed restore compare"
test_pipe dump.orig restore $dumpdev || cbdfr=1
echo
echo "Testing bookworm dump, bookworm restore compare"
test_pipe dump.orig restore.orig $dumpdev || cbdbr=1
echo
echo
echo "Testing fixed dump, fixed restore"
test_file dump restore $dumpdev || tfdfr=1
echo
echo "Testing fixed dump, bookworm restore"
test_file dump restore.orig $dumpdev || tfdbr=1
echo
echo "Testing bookworm dump, fixed restore"
test_file dump.orig restore $dumpdev || tbdfr=1
echo
echo "Testing bookworm dump, bookworm restore"
test_file dump.orig restore.orig $dumpdev || tbdbr=1
echo
umount mnt >& /dev/null
vgchange -an vg30T >& /dev/null
losetup -d ${ld3}
losetup -d ${ld2}
umount d1.mnt
umount d2.mnt
losetup -d ${ld1}
losetup -d ${ld0}
rmdir mnt
rmdir d1.mnt
rmdir d2.mnt
rm -f d1
rm -f d2
rm -fr restore
echo
echo
echo
[[ $tfdfr -eq $cfdfr ]] || echo "SERIOUS BUG --- Mismatch between restore -C
and actual restore for fixed dump and fixed restore" >&2
[[ $tfdfr -eq 0 ]] || echo "SERIOUS BUG --- mismatch between fixed dump and
fixed restore" >&2
[[ $tbdbr -eq $cbdbr ]] || echo "Bookworm BUG -- Mismatch between restore -C
and actual restore for bookworm dump and bookworm restore" >&2
[[ $tbdbr -eq 0 ]] || echo "Bookworm BUG -- mismatch between bookworm dump and
bookworm restore" >&2
[[ $tfdbr -eq $cfdbr ]] || echo "Compatibility - Mismatch between restore -C
and actual restore for fixed dump and bookworm restore" >&2
[[ $tfdbr -eq 0 ]] || echo "Compatibility - Bookworm restore fails to handle
fixed dump data" >&2
[[ $tbdfr -eq $cbdfr ]] || echo "Compatibility - Mismatch between restore -C
and actual restore for bookworm dump and fixed restore" >&2
[[ $tbdfr -eq 0 ]] || echo "Compatibility - Bookworm dump generates invalid
dump data" >&2
--- End Message ---