Hi there, slight necro but this seems like the most appropriate place to share my experiences as it's the quadruple reformat thread.
I too was wondering why there was a need for quadruple reformatting (it seemed kind of redundant compared to the usual single pass of partitioning and building the file system); I might have hints to help demystify the process.
For some background, I came here after running into the offset screen bug with GBA VC on my n3DSXL/128GB micro SD (Sandisk Ultra, in case that's important), and was able to fix that by rebuilding the file system with 64k clusters instead of the previous 32k using GNU Parted and mkfs.fat. However, after this I ran into the issue of saves taking an obscene amount of time (freezing the games for around 10 seconds) in snes9x and the SM64 homebrew. Quadruple reformatting as above with 64k clusters seems to have resolved everything. Additionally, Metroid Fusion GBA VC now loads in around 14 seconds vs the previous 20 or so.
Anyway, the relevant part is that I was wondering what the difference would be (if any) between my previous GNU Parted/mkfs.fat pass on my Linux machine vs the quadruple reformat above, so I cataloged the disk info from fdisk and minfo before and after.
Here's the diff:
Code:
Disk /dev/mmcblk0: 119.08 GiB, 127865454592 bytes, 249737216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
-Disk identifier: 0xf2e2cd8f
+Disk identifier: 0xba5fd1db
Device Boot Start End Sectors Size Id Type
-/dev/mmcblk0p1 2048 249737215 249735168 119.1G c W95 FAT32 (LBA)
+/dev/mmcblk0p1 2048 249737215 249735168 119.1G b W95 FAT32
device information:
===================
filename="/dev/mmcblk0p1"
-sectors per track: 16
-heads: 4
-cylinders: 3902112
+sectors per track: 63
+heads: 255
+cylinders: 15546
media byte: f8
-mformat command line: mformat -t 3902112 -h 4 -s 16 -i "/dev/mmcblk0p1" ::
+mformat command line: mformat -T 249735168 -h 255 -s 63 -H 0 -i "/dev/mmcblk0p1" ::
bootsector information
======================
-banner:"mkfs.fat"
+banner:"MSWIN4.1"
sector size: 512 bytes
cluster size: 128 sectors
-reserved (boot) sectors: 128
+reserved (boot) sectors: 32
fats: 2
max available root directory slots: 0
small size: 0 sectors
media descriptor byte: 0xf8
sectors per fat: 0
-sectors per track: 16
-heads: 4
+sectors per track: 63
+heads: 255
hidden sectors: 2048
big size: 249735168 sectors
physical drive id: 0x80
reserved=0x1
dos4=0x29
-serial number: FA2E8A6C
+serial number: B47BB300
disk label="NO NAME "
disk type="FAT32 "
-Big fatlen=15360
+Big fatlen=15243
Extended flags=0x0000
FS version=0x0000
rootCluster=2
It seems like the main difference is Logical Block Addressing (LBA) vs Cylinder Head Sector. The sectors per track and head values are also now maxed out at 63 and 255 respectively. Perhaps one of the culprits of SD card issues is LBA FAT and the 3DS having a wonky disk controller that doesn't play nicely with it.
I suspect that I could have also solved my problems using my Linux machine if I were to reproduce this diff by manually specifying the sectors per track and head parameters using fdisk instead of using GNU Parted, along with specifying non-LBA FAT and 32 reserved sectors. IIRC these details were obscured in the Windows GUI programs.
I don't think I really care to experiment further now that I'm not having any problems with slow writes/reads, but hopefully this was interesting.
UPDATE:
A little while after originally posting this, SM64 began to exhibit the save slowdown again, albeit not as badly as before. This triggered me to go back on my previous statement and resume experimentation. I think I've now spent enough time playing through the SM64 homebrew and Super Metroid in snes9x to say that I've actually fixed the issues this time around.
There are some technical details you'll need to be familiar with to fully understand this write performance phenomenon (tbh, I would say my current understanding is only partial), but the main takeaway is that we want to align the file system to the size of these things called erase segments.
Apparently this wasn't the case after the quadruple reformatting procedure, although I recall reading some posts that claimed that the SD Association formatter does this. Unfortunately, I didn't think to test that and don't really want to look into it now because it's a little inconvenient to keep formatting and re-copying my 115GB of 3DS data.
Anyway, here's the main source I read that outlines everything. I'm currently not allowed to post links because this is my only post, so instead I'll provide some search terms. Hopefully this is okay.
- 3gfp formatting sd cards for speed and lifetime
And here are some more things to read on the topic:
- stackexchange why does the sd card random write performance for record size 8-128 kb drops below the performance of record size 4 kb
- msfn does fat32 align its clusters
It would also be helpful to have a working understanding of how flash memory and FAT work, to tie things together.
Here's the summary of my procedure (this essentially follows the 3gfp source):
- First, check the segment size:
Code:
$ cat /sys/class/mmc_host/mmc0/mmc0\:aaaa/preferred_erase_size
In my case, this was 4MiB (4194304B). It sounds like this should usually be the case with contemporary SD cards of this class, but in principle I suppose it could be different.
- Partition the card such that the partition table is at the beginning as usual, and the primary partition starts at the first 4MiB boundary. For me, this first boundary is at 8192 sectors with 512k sector sizes.
I used fdisk for this. I also set the partition type as 0x0b for non-LBA FAT32 and specified "-H 255 -S 63" to set the number of heads and sectors per track to match the diff in my initial post.
- Build the file system. I used mformat from mtools instead of mkfs.fat because mkfs.fat would set the heads and sectors per track values back to 4 and 16, respectively. However, after this round of experimenting, I'm not entirely sure whether these values are actually important. I didn't specifically test for this because of the aforementioned inconvenience of re-copying all my data to test the system.
Otherwise, I essentially followed the 3gfp post:
First, format the card without specifying any reserved sectors and check the size of the FAT ("Big fatlen" in the output of minfo -i) and the number of FATs (in my case, 2), then calculate the size of the boot sector by multiplying these together. In my case, this was 15241 * 2 = 30482.
Code:
$ sudo mformat -T 249729024 -h 255 -s 63 -F -H 8192 -c 128 -i "/dev/mmcblk0p1" ::
$ sudo minfo -i /dev/mmcblk0p1
Then, rebuild the file system with an appropriate number of reserved sectors to pad the end of the boot sector to align with a 4MiB boundary. In this case the nearest boundary is 16MiB, at 32768 sectors. Therefore, I needed 32768 - 30482 = 2286 reserved sectors.
This also ensures that the FAT clusters are boundary-aligned as 4MiB is a multiple of the cluster size.
Code:
$ sudo mformat -T 249729024 -h 255 -s 63 -F -H 8192 -c 128 -R 2286 -i "/dev/mmcblk0p1" ::
At this point, it should be good to go, but you can check that the alignment matches your calculation with dosfsck (truncated output):
Code:
$ sudo dosfsck -vn /dev/mmcblk0p1
...
Data area starts at byte 16777216 (sector 32768)
...
Here's the diff from this vs. quadruple reformat:
Code:
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
-Disk identifier: 0xba5fd1db
+Disk identifier: 0xce89f1a1
Device Boot Start End Sectors Size Id Type
-/dev/mmcblk0p1 2048 249737215 249735168 119.1G b W95 FAT32
+/dev/mmcblk0p1 8192 249737215 249729024 119.1G b W95 FAT32
device information:
===================
filename="/dev/mmcblk0p1"
sectors per track: 63
heads: 255
-cylinders: 15546
+cylinders: 15545
media byte: f8
-mformat command line: mformat -T 249735168 -h 255 -s 63 -H 0 -i "/dev/mmcblk0p1" ::
+mformat command line: mformat -T 249729024 -h 255 -s 63 -H 0 -i "/dev/mmcblk0p1" ::
bootsector information
======================
-banner:"MSWIN4.1"
+banner:"MTOO4025"
sector size: 512 bytes
cluster size: 128 sectors
-reserved (boot) sectors: 32
+reserved (boot) sectors: 2286
fats: 2
max available root directory slots: 0
small size: 0 sectors
@@ -40,15 +40,15 @@
sectors per fat: 0
sectors per track: 63
heads: 255
-hidden sectors: 2048
-big size: 249735168 sectors
-physical drive id: 0x80
-reserved=0x1
+hidden sectors: 8192
+big size: 249729024 sectors
+physical drive id: 0x0
+reserved=0x0
dos4=0x29
-serial number: B47BB300
+serial number: 3E7F1AC4
disk label="NO NAME "
disk type="FAT32 "
-Big fatlen=15243
+Big fatlen=15241
Extended flags=0x0000
FS version=0x0000
rootCluster=2
@@ -57,3 +57,26 @@
Infosector:
signature=0x41615252
We can see the differences in partition alignment and reserved sectors.
For fun, I also dug out the stock Toshiba 4GB micro SD that came with the n3DSXL and checked its partition table/formatting:
Code:
Disk /dev/mmcblk0: 3.64 GiB, 3904897024 bytes, 7626752 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000000
Device Boot Start End Sectors Size Id Type
/dev/mmcblk0p1 8192 7626751 7618560 3.6G b W95 FAT32
device information:
===================
filename="/dev/mmcblk0p1"
sectors per track: 63
heads: 128
cylinders: 945
media byte: f8
mformat command line: mformat -T 7618560 -h 128 -s 63 -H 0 -i "/dev/mmcblk0p1" ::
bootsector information
======================
banner:" "
sector size: 512 bytes
cluster size: 64 sectors
reserved (boot) sectors: 6332
fats: 2
max available root directory slots: 0
small size: 0 sectors
media descriptor byte: 0xf8
sectors per fat: 0
sectors per track: 63
heads: 128
hidden sectors: 8192
big size: 7618560 sectors
physical drive id: 0x80
reserved=0x1
dos4=0x29
serial number: E6D08679
disk label="NO NAME "
disk type="FAT32 "
Big fatlen=930
Extended flags=0x0000
FS version=0x0000
rootCluster=2
infoSector location=1
backup boot sector=6
Infosector:
signature=0x41615252
We can see that it's also partitioned/file system aligned to 4MiB boundaries, and has a partition type of non-LBA FAT32. This at least gives me some more confidence that it might be more desirable to specify non-LBA FAT32. However, I'm not sure whether this actually matters and think that my main problem was the alignment.
Again, hopefully this helped or was interesting.