Table des matières

Récupérer l'espace consommé par .thumbnails

Cette fiche a un statut particulier car elle ne propose aucune solution. C'est plutôt une fiche d'enquête.

Le problème tel qu'il est énoncé

Un androphone signale qu'il manque de mémoire de stockage (sdcard). L'analyse de l'occupation de la mémoire fait apparaître qu'un fichier appelé “.thumbnails” occupe plusieurs Go1). De nombreuses utilisatrices rapportent ce problème.

Le nom du fichier laisse entendre qu'il est dédié au stockage de vignettes pour des médias. Le cas le plus simple est celui de la vignette d'une image qui sera affichée dans plusieurs applications, particulièrement dans la galerie d'image. Or la taille de .thumbnails semble totalement décorrélée de la taille des médias réellement stockés sur l'androphone. La taille de .thumbnails peut même dépasser la taille des médias (en plein format) enregistrés dans la mémoire interne et la carte SD externe !

Localisation

Selon les version d'Android et les applications utilisées, le nom et la localisation de ce conteneur encombrant peut varier. Dans le cas étudié, le fichier fautif est situé dans le répertoire “/sdcard/DCIM/.thumbnails/”. Le fichier lui-même s'appelle “.thumbdata4-1967290299”.

Récupérer l'espace indûment consommé

Comme indiqué dans l'énoncé du problème, l'objectif poursuivi est de récupérer de l'espace de stockage.

Les solutions qui n'en sont pas

Internet regorge de propositions pour résoudre ce problème. Toutes passent par la suppression du fichier fautif. Mais cette opération semble vaine car le fichier est recréé par l'application. Certaines variantes proposent des astuces pour bloquer cette recréation. Mais aucune de ces “solutions” ne permet de récupérer l'espace considérable consommé par le fichier fautif.

Hypothèses explicatives

Plusieurs explications peuvent être apportées à la non récupération de l'espace de stockage utilisé par le fichier fautif :

  1. en vrai, le fichier n'est pas effacé, comme cela peut se produire sur un système complexe tel Linux
  2. il n'est pas effacé proprement et l'espace qu'il occupait est dans un état bizarre qui empêche qu'il soit allouer à de nouveaux fichiers
  3. la taille annoncée par le fichier est trompeuse si bien qu'en effaçant ce dernier on ne récupère pas l'espace qu'on lui croyait alloué.

Analyse des hypothèses

Une taille de fichier trompeuse

Commençons par la dernière hypothèse. Elle peut sembler la plus loufoque mais il n'en est rien. Certains types de fichiers peuvent avoir une taille déclarée bien supérieure à l'espace de stockage qu'ils consomment réellement. Ce type de fichier n'existe pas dans tous les systèmes de fichiers mais on le trouve dans les systèmes de fichiers courants sur Linux et donc Android (ext2, ext2, ext4…). On parle de fichiers “sparse”.

L'apparition d'un tel fichier n'est pas un signe de compromission de votre androphone. L'utilisation d'un fichier sparse unique pour y stocker des centaines de vignettes est l'un des cas où une telle implémentation peut se justifier2).

Dans les cas extrêmes, une application telle que Memory Mapp donne un indice sérieux d'écart entre les tailles déclarée et allouée. Durant “l'analyse du disque”, le pourcentage de progression dépasse 100%3).

Préparatifs

Le cas traité est celui d'un téléphone rooté. Le principe est d'ouvrir un shell sur l'androphone en cours d'utilisation sous Android et d'utiliser les commandes classiques pour analyser le contenu des systèmes de fichiers présents. Des applications permettent d'ouvrir un terminal sur l'androphone mais il est beaucoup plus confortable de connecter l'androphone à un ordi. C'est la voie qui sera suivie dans ce qui suit.

linux:~$ adb shell
kiwi:/ $ su
:/ # 
130|:/ # whoami
root
:/ # uname -r
3.10.108-lineageos-g6e87014
:/ # 

Après la connexion, on fait en sorte de devenir “root” et l'on constate que l'on est bien sur système Android (ici LineageOS). Pour une vue d'ensemble de l'espace disponible, on utilise la commande df (disk free) :

:/ # df
Filesystem                    1K-blocks     Used Available Use% Mounted on
tmpfs                         921M  636K  920M   1% /dev
tmpfs                         921M     0  921M   0% /mnt
/dev/block/mmcblk0p24         2.4G  1.5G  894M  65% /system
/dev/block/mmcblk0p17          63M  3.7M   59M   6% /log
/dev/block/mmcblk0p23         496M  477M   19M  97% /cust
/dev/block/mmcblk0p22         248M  196K  248M   1% /cache
/dev/block/mmcblk0p18          59M  344K   59M   1% /persist
/dev/block/mmcblk0p14         200M   53M  146M  27% /firmware
/dev/block/mmcblk0p26          7.5G  3.0G  72% /data
/data/media                    7.5G  3.0G  72% /mnt/runtime/default/emulated
/dev/block/vold/public:179,65  30G   19G   11G  64% /mnt/media_rw/4B7E-1AC3
/mnt/media_rw/4B7E-1AC3        30G   19G   11G  64% /mnt/runtime/default/4B7E-1AC3

En se laissant guider par les noms et les tailles, on identifie rapidement la carte SD interne “/data/media” (émulée) et la carte SD externe “/mnt/media_rw/4B7E-1AC3”. Sans entrer dans les détails, il est normal que le même espace de stockage apparaisse deux fois, avec des noms de système de fichier différent, montés en des points différents. Les noms de référence sont ceux qui commencent par “/dev…” ; considérez les autres comme des alias. Soit :

On vérifie que le système de fichiers utilisé par le stockage interne est bien du type ext44) :

:/ # df -ht ext4                                                               
Filesystem            Size  Used Avail Use% Mounted on
…
/dev/block/mmcblk0p26  11G  7.5G  3.0G  72% /data

Ici, la carte SD externe est du type vfat :

:/ # df -ht vfat                                                               
Filesystem                    Size  Used Avail Use% Mounted on
…
/dev/block/vold/public:179,65  30G   19G   11G  64% /mnt/media_rw/4B7E-1AC3

Avant de foncer tête baissée pour éradiquer un fichier fautif, il n'est pas inutile d'avoir une vue d'ensemble de la consommation de l'espace de stockage interne5) :

:/ # du -a -d1 /data | sort -n -r | head -n 20                                 
7922948 /data
3413868 /data/app
2133432 /data/data
1730308 /data/media
462580  /data/user_de
147700  /data/dalvik-cache
18744   /data/system
9660    /data/misc
2452    /data/system_ce
2328    /data/tombstones
880     /data/backup
380     /data/system_de
164     /data/misc_ce
72      /data/resource-cache
60      /data/vendor
60      /data/time
28      /data/mediadrm
28      /data/cache
20      /data/drm
20      /data/anr

La carte SD émulée sur la mémoire interne de l'androphone se trouve à l'intérieur du répertoire /data/media. Dans l'exemple, on constate qu'elle n'est qu'au troisième rang et consomme 1,65 Go.

Dans la suite, afin de simplifier l'affichage, on utilise le raccourci mis en place par Android qui associe le répertoire /sdcard à un sous-répertoire de /data/media (/data/media/0).

On affine la recherche en se focalisant sur ce répertoire :

:/ # cd sdcard
:/sdcard # du -a -d1 | sort -n -r | head -n 10
1730288 .
637324  ./Android
372916  ./Music
368800  ./DCIM
243156  ./DictionariesNGHS
26684   ./.estrongs
22292   ./Download
12280   ./osmdroid
10224   ./HWThemes
9368    ./data

À ce stade, on dispose d'une photographie réaliste de l'utilisation de l'espace de stockage mis à notre disposition sous forme de carte SD émulée en mémoire interne.

Validation de l'hypothèse

La différence entre la taille déclarée et taille allouée est vérifiable à travers des commandes standard. Typiquement, la commande “ls”6) indiquera la taille déclarée tandis que la commande “du”7) indiquera l'espace de stockage utilisé.

Poussons l'exercice jusqu'au bout et assurons nous que le répertoire .thumbails et le fichier .thumbdata4–1967290299 qui nous préoccupaient sont rentrés dans le rang.

kiwi:/ $ cd sdcard/DCIM/.thumbnails/
kiwi:/sdcard/DCIM/.thumbnails $ ls -lh .thumbdata4--1967290299
-rw-rw---- 1 root sdcard_rw 8.9G 2020-08-02 13:35 .thumbdata4--1967290299
kiwi:/sdcard/DCIM/.thumbnails $ du -h .thumbdata4--1967290299
56K     .thumbdata4--1967290299
/dev/block/mmcblk0p26    11G  7.6G  2.7G  74% /data

Dans le cas étudié, la démonstration est frappante :

Autrement dit, la suppression de ce fichier permettrait de gagner 56K. Pas un octet de plus ! Dans ces conditions, si votre androphone manque de mémoire de stockage interne disponible, il faut trouver un autre «fautif» et d'autres moyens d'en libérer.

Cas inverse

Ne soyez pas surprise si vous observez le cas inverse à celui qui nous préoccupe ici. Oui, il est possible que la taille déclarée d'un fichier soit inférieure à la taille utilisée pour le conserver. Cela est particulièrement visible si on crée un fichier texte de 1 caractère. La commande ls indiquera que sa taille est de 1 octet alors qu'il occupera au minimum la taille d'un bloc d'allocation sur disque (par exemple, 4.0 Ko).

$ echo > test
$ ls -lh test                                                 
rw-rw---- 1 root sdcard_rw 1 2018-07-01 15:47 test
$ du -h test
4.0K    test

Le fichier survit à une tentative d'effacement

La première hypothèse est que la demande de suppression de fichier serait bien enregistrée mais qu'elle serait mise en attente ou simplement ignorée, de manière non visible. Cette incertitude vient notamment du fait que le système (ici Android) est en cours d'exécution et qu'en conséquences, certains programmes (app ou système) peuvent être en train de lire ou d'écrire dans le fichier.

S'assurer de la suppression

Sur internet, on trouvera plusieurs propositions d'apps permettant de supprimer un fichier de manière fiable. La manière la plus fiable est encore de ne pas le faire depuis une application ni même depuis Android.

La solution consiste à démarrer l'androphone sur le recovery8) et à utiliser le navigateur de fichier du recovery pour supprimer le fichier fautif. Dans ce cas, la mémoire interne de stockage est traitée comme un vulgaire “disque externe”, sans lien avec le système (recovery) en cours d'exécution.

Sur l'androphone utilisé au cours de cette analyse, la suppression a porté sur tout le répertoire .thumbnails. Après redémarrage sous Android9), le répertoire a été recréé automatiquement, ainsi que le fichier “fautif”, mais avec une taille nulle.

:/sdcard # cd DCIM/.thumbnails
:/sdcard/DCIM/.thumbnails # ls -alh
total 4.0K
drwxrwx--x 2 root sdcard_rw 4.0K 2020-07-26 13:05 .
drwxrwx--x 5 root sdcard_rw 4.0K 2020-08-01 16:00 ..
-rw-rw---- 1 root sdcard_rw    0 2020-07-26 13:05 .thumbdata4--1967290299
:/sdcard/DCIM/.thumbnails # du -ah                                             
0       ./.thumbdata4--1967290299
4.0K    .
  1. ls nous informe que la taille déclarée du fichier est de 0 octet
  2. du nous affirme que l'espace réellement utilisé est également de 0 octet.

Ces valeurs étant constantes après plusieurs jours d'utilisation de l'androphone10), on peut raisonnablement en conclure que l'opération de nettoyage a porté ses fruits.

L'utilisation d'autres applications manipulant les images a entraîné l'insertion d'images dans le répertoire .thumbnails et un début de remplissage du fichier .thumbdata4–1967290299. On est alors ramenée à la situation décrite précédemment.

Quelques sources

Pages du manuel des commandes Linux

Dans cet fiche, on utilise peu de commandes : ls, du, df. Il est toujours intéressant de consulter les pages du manuel mais l'implémentation de ces commandes n'est pas uniforme d'un système à l'autre. La recommandation “lisez le manuel” s'applique à la documentation installée sur le système où vous utilisez cette commande. Dans le cas d'espèce, il n'y a pas de documentation installée sur l'androphone. Heureusement, les commandes sont auto-documentées de manière minimale. Pour obtenir l'information on exécute la commande avec l'option “–help”, par exemple :

kiwi:/ $ df --help
usage: df [-HPkhi] [-t type] [FILESYSTEM ...]

The "disk free" command shows total/used/available disk space for
each filesystem listed on the command line, or all currently mounted
filesystems.

-a      Show all (including /proc and friends)
-P      The SUSv3 "Pedantic" option
…

Les versions des commandes disponibles sur LineageOS 16 offrent bien moins d'options que celles que l'on trouve sur un système GNU-Linux courant.

Sur le ouèbe

1)
Dans le cas étudié, il occupe 8,9 Go sur une mémoire de stockage totale de 11 Go !
2)
Comparaison n'est pas raison, mais c'est un peu comme l'utilisation des sprites conjointement à CSS sur certaines applications Web.
3)
En effet, cette application s'appuie sur la taille réelle du “disque” et sur la taille déclarée des fichiers. Supposons que le disque fasse 10 Go, que les fichiers non sparse occupent 6 Go et qu'un fichier sparse soit déclaré à 8 Go, Memory Map affichera une analyse à 140% du disque (8+6)/10).
4)
Ça semble un peu magique car il faut avoir la prescience du type de système de fichiers. En effet, la version de df disponible sur cette version de LOS (toybox 0.7.6-android) ne reconnaît pas l'option “-T” qui permettrait d'afficher le type de tous les systèmes de fichiers affichés. Heureusement, on peut obtenir cette information avec la commande mount sans aucun paramètre (âmes sensibles à l'overdose de code s'abstenir).
5)
On combine du qui calcule l'utilisation effective de mémoire dique avec sort qui trie la liste des fichiers-répertoires et head qui ne retient que les première lignes…
6)
List.
7)
Disk Usage.
8)
Un système dédié à la maintenance, alternatif à l'Android qui motorise votre androphone.
9)
Ici LOS16
10)
Navigation dans la gallerie d'images, prises de photos, envoi et réception d'images via différentes applications…