[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Troubles with updating Debian Hurd

Ignoring both syslog and vim did the trick! The final command was:

# debootstrap --keyring=/usr/share/keyrings/debian-ports-archive-keyring.gpg
--extra-suites=unreleased --exclude vim,vim-tiny,rsyslog sid
/tmp/subhurd/ http://deb.debian.org/debian-ports/

Now, I ran into another issue, which is this time actually related to
the Hurd rather than Debian. The wiki page on subhurds says:

> To create a file my.image of size 2 gigabytes, do
> $ dd if=/dev/zero of=my.image bs=1M count=1 seek=2000
> (Note that it is currently problematic to create files larger than 2 gigabytes this way.)

and that's what I have done previously. This time I thought I'd be
clever and create the 2GB file using truncate(1) instead of dd(1),
which resulted in my newly installed subhurd refusing to boot:

ext2fs: pseudo-root: panic: main: device too small for superblock
(-2147483648 bytes)

And yet the same file is perfectly mountable with the very same
ext2fs.static binary outside of the subhurd boot process. What gives?

So I've traced what causes this issue; dumping it here so it doesn't get lost:

2 GB (2 * 1024³, as opposed to whatever 2000 * 1M means) is just
enough to wrap around a signed 32-bit integer, giving -2147483648.
ext2fs uses libstore to access the fs image. libstore uses 64-bit

libstore's file backend sets the block size to 1, and size to st_size.
Its device backend queries the device size using device_get_status
(DEV_GET_RECORDS), which returns size / block size in two (32-bit)
ints! How's it not an issue in all other cases, e.g. how come my main
Hurd box even boots? Well, normally block ("record") size is something
like 512, so the minimum device size to cause wraparound is 1204 GB (2
* 1024³ 512-byte blocks). Not that unrealistically large though.

When running a subhurd, boot(1) presents it with a pseudo-root device
that supports device.defs RPCs and is backed by another store on the
host. When queried for DEV_GET_RECORDS, boot(1) responds with
libstore's idea of block size and size in blocks. Which in case of a 2
GB regular file is (1, 2 * 1024³), which wraps around the 32-bit
integer. Boom.

A low-hanging-fruit fix would be to treat the size as unsigned in
libstore (and all other users of device_get_status), this would get us
to 4 GB & 2048 GB. It should also be possible for boot(1) to emulate a
block size of 512 (or something) instead of blindly forwarding what it
gets from libstore; but I'm not sure how that would work if the file
size is not divisible by 512. A proper fix would be to extend
device_get_status () to support sizes that don't fit into a single
32-bit int; perhaps by using a third int and a new "flavor".

Hope this makes sense.


Reply to: