[Toybox] [landley/toybox] stat: block size differences (#41)

Rob Landley rob at landley.net
Thu Aug 11 07:37:21 PDT 2016


On 08/11/2016 03:49 AM, Matthias Urhahn wrote:
> Toybox 0.7.1, Busybox 1.24.2
> On a Nexus5 at 6.0.
> 
> Why is there a difference in blocksize?
> 
> |root at hammerhead:/sdcard # busybox stat -c %B:%b:%o:%s
> twrp-3.0.0-0-hammerhead.img 512:28632:4096:14657536
> root at hammerhead:/sdcard # toybox stat -c %B:%b:%o:%s
> twrp-3.0.0-0-hammerhead.img 4096:28632:4096:14657536 |
> 
>     %B Bytes per block

In toybox, both %o and %B come from the stat() system call.

  else if (type == 'B') out('u', stat->st_blksize);

  } else if (type == 'o') out('u', stat->st_blksize);

I.E. we're telling you what the operating system told us (presumably
getting it from the filesystem driver).

A quick check shows busybox is printing a hardwired value for %B but the
stat value for %o:

        } else if (m == 'B') {
                strcat(pformat, "lu");
                printf(pformat, (unsigned long) 512); //ST_NBLOCKSIZE

        } else if (m == 'o') {
                strcat(pformat, "lu");
                printf(pformat, (unsigned long) statbuf->st_blksize);

I don't understand the point of printing a hardwired value for %B? FAT
block sizes vary from 512 bytes up to 65535k. ext2 can be 1k or 4k.

A few years ago hard drives went from 512 byte physical block to 4k,
which caused some problems because of longstanding assumptions:

  https://lwn.net/Articles/322777/
  https://lwn.net/Articles/377895/

And now the sectors are getting bigger:

  https://lwn.net/Articles/582862/

Here's some articles about the damage conflicting block size assumptions
can do (data loss when an interrupted write changes stuff you didn't
think was being rewritten) and ways around it:

  https://lwn.net/Articles/349970/
  https://lwn.net/Articles/665299/
  https://lwn.net/Articles/353411/

You shouldn't have to care about 90% of that (the OS handles it all for
you), but from my perspective having two ways to query block size would
be really nice if the OS gave me a way to determine the block size of
the physical media, as distinct from the block size of the filesystem.
Unfortunately, although it _seems_ like %B would be filesystem block
size and %o would be physical media block size, Linux doesn't give me a
way to query physical media block size that I've noticed. (I might be
able to beat it out of the mtd layer for some types of flash?)

> busybox says 512Byte while toybox says 4096Byte.

Busybox is returning a single hardwired answer.

That said, it looks like the Ubuntu version is also doing that. If %B
should always say "512" regardless of context, I can make it do that and
change the help text to say something like:

  %B  prints "512"

> 28632 Blocks * 512Byte = 14659584 Byte
> Which is a lot closer to the actual file size of 14657536 Byte (reported
> by both toybox&busybox).

More stat fields: %b is st_blocks and %s is st_size.

The stat(2) man page says that st_blocks is "number of 512B blocks
allocated" so %B is units for %b (and yes, it's a hardwired value). So
the help text should be something like:

  %B  units for %b (always 512)

> Other commands from both binaries also show a block size of 4096 Byte
> though.

The "man 1 stat" page says:

       %B     the size in bytes of each block reported by %b

The "man 2 stat" page says:

       blkcnt_t  st_blocks;  /* number of 512B blocks allocated */

So yes, you've found an inconsistency and I should fix it. %B should
output a hardwired "512", busybox is correct here.

Thanks. Good catch,

Rob


More information about the Toybox mailing list