3

On an Android Nougat (7.1.1) set top box, du and df of my /data partition are very different:

$ adb shell du -sh /data
1.0G    /data
$ adb shell df -H /data
Filesystem      Size  Used Avail Use% Mounted on
/dev/block/sda9  10G   10G  469M  96% /data

I don’t think that anything else is mounted under /data:

$ adb shell mount | grep "\/data"
/dev/block/sda9 on /data type ext4 (rw,seclabel,nosuid,nodev,relatime,discard,noauto_da_alloc,data=ordered)
$ adb shell mount | grep "sda9"
/dev/block/sda9 on /data type ext4 (rw,seclabel,nosuid,nodev,relatime,discard,noauto_da_alloc,data=ordered)

lsof indicates to me that there are dozens of processes holding hundreds of small deleted files of the sort

init          1       root    3w      CHR               1,11       0t0      14517 /dev/__kmsg__ (deleted)
ueventd     391       root    3w      CHR               1,11       0t0      14593 /dev/__kmsg__ (deleted)
  . . .
main        756       root  mem   unknown                                         /dev/ashmem/dalvik-large object space allocation (deleted)
main        756       root  mem   unknown                                         /dev/ashmem/dalvik-large object space allocation (deleted)
  . . .
omm.times  3934     system  mem   unknown                                         /dev/ashmem/dalvik-mark sweep sweep array free buffer (deleted)
omm.times  3934     system  mem   unknown                                         /dev/ashmem/dalvik-mark sweep sweep array free buffer (deleted)

Using busybox, results are different (df shows much less usage), but there is still a large discrepancy between du and df:

$ adb shell busybox du -sh /data
389.4M  /data
$ adb shell busybox df -h /data
Filesystem                Size      Used Available Use% Mounted on
/dev/block/bootdevice/by-name/userdata
                          9.7G      8.6G      1.1G  89% /data

And using toybox, the results are similar to busybox:

$ adb shell toybox du -sh /data
389M    /data
$ adb shell toybox df -h /data
Filesystem      Size  Used Avail Use% Mounted on
/dev/block/sda9  10G  8.6G  1.1G  89% /data

It think that it's important to note that these numbers remain similar after a reboot.

Also, I wish to note that I cannot OTA update this device's Android due to running out of disk space, even though the OTA image is only about 1GB in size. This fact leads me to believe that the results of df are accurate in terms of actual available disk space.

All adb commands are run as root i.e., I did adb root before executing them. But at risk of making this question be too verbose, here's everything run at the adb prompt:

$ adb shell
Z:/ # whoami
root
Z:/ # du -sh /data
389M    /data
Z:/ # df -h /data
Filesystem      Size  Used Avail Use% Mounted on
/dev/block/sda9  10G  8.6G  1.1G  89% /data
10.197.12.14:/ # busybox du -sh /data
389.4M  /data
Z:/ # busybox df -h /data
Filesystem                Size      Used Available Use% Mounted on
/dev/block/bootdevice/by-name/userdata
                          9.7G      8.6G      1.1G  89% /data
Z:/ # toybox du -sh /data
389M    /data
Z:/ # toybox df -h /data
Filesystem      Size  Used Avail Use% Mounted on
/dev/block/sda9  10G  8.6G  1.1G  89% /data
Z:/ # 

A user in comments has asked for the following:

Z:/ # while read num; do (( sum += num )); done <<< $(find /data -type f -exec stat -c%b {} +); expr $sum / 2048
393

I understand that du reports free space by scanning reachable nodes, and that this could therefore mean that my file system is corrupt. However, unfortunately, this is for devices in the field, and I don’t want to have to (and don’t think I can) run fsck or e2fsck.

What might be causing the huge difference between du and df on this device, and how might this problem be resolved? I’m happy to provide further logs.

alecxs
  • 4,034
  • 3
  • 16
  • 34
zippy
  • 41
  • 5
  • df and du mostly differ somewhat (see here why) but not that much. There seems to be some problem with your du binary. Use a different one. See here what you should expect: How disk space is used on Android device? – Irfan Latif Feb 23 '21 at 16:31
  • You've called to both as "normal user". So df can report the "free space" (aka "Disk Free") normally – while du can only sum up what the user has access to. Nothing broken, works as designed. Try both as root, see the screenshot by @alecxs – Izzy Feb 23 '21 at 19:46
  • Thanks, @IrfanLatif. I added busybox results to the original question. – zippy Feb 23 '21 at 22:36
  • 1
    @Izzy Per my original description, I called them as root. – zippy Feb 23 '21 at 22:37
  • @zippy your original description shows your commands prefixed with a $. Commands called as root carry a #. But I indeed missed your comment on adb root (also as it's quite uncommon; I never had a ROM allowing me that on any of my devices, not even custom ROMs). But yes, you can run fsck (even in read-only mode if you prefer), it is available on-device. – Izzy Feb 24 '21 at 07:47
  • https:/i.stack.imgur.com/n0cBI.png https:/i.stack.imgur.com/qwTbp.png – alecxs Feb 24 '21 at 07:58
  • @alecxs -- I put the results of that command into the description. Our busybox is here: https://links-w.astronics.com/MBSlU8bHA_k/ password "busybox.zip" without the quotes. And what I haven't mentioned yet is that I cannot OTA upgrade this unit due to disk full (!). – zippy Feb 24 '21 at 19:12
  • 393M sum of all files (with read access) is congruent with du. busybox v1.15.3 works fine too. thought about hard-links but that should produce opposite results, so no idea :( – alecxs Feb 24 '21 at 20:49
  • check *'du -sh /proc/*/*/mnt'* (not sure this is helpful as i have disabled mount namespace separation in SuperSU completely and don't know how to check) – alecxs Feb 26 '21 at 11:04
  • The reason for a delay in responding is that a customer was visiting this week. @alexcs, I tried the remount, but it doesn't seem to have an effect. I'm also trying to build an fsck for Nougat on aarch64 on toybox (there is none built in) but that's not working. Can anyone point me to an aarch64 fsck? – zippy Feb 26 '21 at 16:40
  • /system/bin/e2fsck – alecxs Feb 26 '21 at 23:00
  • 1
    please try to set selinux permissive with setenforce/getenforce. Now lazy umount, kill system_server, re-mount sda9 to another dir and check again – alecxs Feb 27 '21 at 06:54
  • today got Mecool KII Pro S905D on my hands. realized these tv box are shipped with busybox pre-rooted userdebug builds. selinux is permissive but namespaces are isolated. with no superuser app at all no clue how to set global – alecxs Mar 07 '21 at 07:37

2 Answers2

2

df stands for "Disk Free". That means, it just needs to check with the "global file system information" about free space (accessible for all users). The size of the file system itself is also "globally available". The difference logically is the "used space". Done.

du works differently: not on file system level but on file level. It needs to look up each directory and file separately, gather it's size, and sum that up. So it can only take into account what it has access to.

Now you've run both commands as "normal user" – who has no permission to traverse e.g. /data/data (where all the apps' data is stored). So it can only sum up a portion of what space is occupied on /data. Would you run both commands as root user (as the screenshot in the comment by alecxs shows), numbers would be much closer together – as usually root can access all files. Though as again Alex correctly points out: there is still SELinux which might deny full access – which according to him is a known issue for mtk-su on the Amazon FireTV stick, and might be the culprit here, and isolated mount namespaces could be yet another reason for invisible files.

TL;DR: there's neither a file system corruption, nor a broken du binary necessarily causing the difference. All might work as designed. If you want to make sure, you can run fsck (if you prefer, in read-only mode) to rule out the former – and set up a test case on a different place for the latter.

Izzy
  • 91,166
  • 73
  • 343
  • 943
  • 1
    per the comment in my description, I already ran du and df as root. Here is confirmation: $ adb shell

    Z:/ # su

    Z:/ # whoami

    root

    Z:/ # du -sh /data

    389M /data

    Z:/ # df -H /data

    Filesystem Size Used Avail Use% Mounted on

    /dev/block/sda9 10G 9.2G 1.1G 89% /data

    – zippy Feb 23 '21 at 22:27
  • Yes, apologies – I missed that in the last paragraphs (got distracted by those huge images in the comments below – no idea why SE meanhile displays them inline, bad idea IMHO). If you want I can hence remove my answer as "invalid". Or I can leave it as it might help those not being aware of the different approaches. – Izzy Feb 24 '21 at 07:49
  • I prefer that you delete it because it doesn't directly address the question (and I had found that these procedures need to be done as root elsewhere). Thanks. – zippy Feb 24 '21 at 19:13
  • 1
    Conflicting wishes. @zippy does my edit change your mind? – Izzy Feb 24 '21 at 23:04
1

The /data partition was indeed corrupted.

After running e2fsck -p /dev/block/sda9, here was the updated du and df (again, after doing an adb root):

$ adb shell du -s /data
1.3G    /data
$ adb shell df -H /data
Filesystem      Size  Used Avail Use% Mounted on
/dev/block/sda9  10G  1.5G  8.9G  15% /data

After fixing the file system, the device ran properly and updated successfully thereafter.

(Note that I found that I had to run e2fsck with the -p option; it wouldn't run interactively for some reason.)

A portion of the output of the above e2fsck command is

data contains a file system with errors, check forced.
data: Deleted inode 163845 has zero dtime.  FIXED.
data: Deleted inode 163847 has zero dtime.  FIXED.
data: Deleted inode 163849 has zero dtime.  FIXED.
   . . . [snip ] . . .
data: Deleted inode 213003 has zero dtime.  FIXED.
data: Deleted inode 262223 has zero dtime.  FIXED.
data: Deleted inode 303108 has zero dtime.  FIXED.
data: 5203/655360 files (2.0% non-contiguous), 186831/2621440 blocks

There were a total of 140 lines of the sort data: Deleted inode...

FWIW, we are guessing that this problem was possibly caused by the filesystem becoming full with logs, which then caused corruption during the next attempted download of OTA updates: Those downloads failed, but thereafter left the file system in a corrupted state. Subsequent attempts at those downloads seemed to further corrupt the file system.

Thanks very much to @alecxs for your persistence and relevant details. (However, please note that to run e2fsck, the partition /dev/block/sda9 had to be UNmounted.)

zippy
  • 41
  • 5