When running F3 on macOS with exFAT-formatted devices, the tool may report systematic data corruption (typically exactly one cluster, e.g. 128 KB = 256 sectors) even on brand-new, healthy storage.
After extensive investigation, this appears to be a tool–OS–filesystem semantic mismatch, not actual media corruption.
This issue does not reproduce on:
Observed Symptoms
Typical output from f3read on macOS + exFAT:
-
Exactly one missing or corrupted cluster
-
Often 128 KB (256 sectors)
-
Reported as corrupted or overwritten
-
More visible on HDDs or slower devices
Example:
Corrupted: 128.00 KB (256 sectors)
exfat fs default cluster = 128KiB (256 sectors)
Root Cause Analysis
static int bdev_write_blocks(struct device *dev, const char *buf,
uint64_t first_pos, uint64_t last_pos)
{
struct block_device *bdev = dev_bdev(dev);
const int block_order = dev_get_block_order(dev);
size_t length = (last_pos - first_pos + 1) << block_order;
off_t offset = first_pos << block_order;
off_t off_ret = lseek(bdev->fd, offset, SEEK_SET);
int rc;
if (off_ret < 0)
return - errno;
assert(off_ret == offset);
rc = write_all(bdev->fd, buf, length);
if (rc)
return rc;
rc = fsync(bdev->fd); // <----- Not ready sync in macOS with exfat
if (rc)
return rc;
return posix_fadvise(bdev->fd, 0, 0, POSIX_FADV_DONTNEED); // <----- Drop page cache but not ready sync data to storage, data lose...
}
Key point
On macOS, fsync() does NOT guarantee physical media persistence.
This is a documented semantic difference from Linux.
What F3 currently does (simplified)
write(...) fsync(fd) posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED)
What happens on macOS + exFAT
-
write() populates the page cache
-
fsync() flushes known dirty pages, but:
- does not guarantee all delayed clusters are committed
-
The last cluster (commonly one exFAT cluster = 128 KB) may still be pending
-
POSIX_FADV_DONTNEED aggressively discards page cache
-
On subsequent read():
👉 Result: exactly one missing cluster, consistently aligned to exFAT cluster size.
This is not a block alignment issue, not an ioctl issue, and not a hardware failure.
Why APFS Does Not Show This Problem
APFS uses:
Therefore, F3’s assumption:
“fsync means data is safely persistent”
happens to hold on APFS, but does not hold on exFAT.
Why This Is Not an exFAT “Bug”
exFAT:
macOS’s exFAT driver prioritizes performance and allows delayed allocation.
The behavior is legal under POSIX and macOS semantics.
Why This Is Dangerous
In reality, the data may never have been written incorrectly at all.
Recommended Fixes
Option 1 (Best): Use macOS-specific full sync
On macOS, replace fsync() with:
fcntl(fd, F_FULLFSYNC)
This guarantees data reaches physical media.
Option 2: Remove POSIX_FADV_DONTNEED on macOS + exFAT
Avoid dropping page cache immediately after fsync() on macOS.
Option 3: Document the limitation clearly
At minimum, warn users:
F3 results on macOS + exFAT may be unreliable unless F_FULLFSYNC is used.
Summary
-
This is not hardware corruption
-
This is not block misalignment
-
This is a filesystem + OS semantic mismatch
-
F3’s assumptions are valid on Linux and APFS
-
They are not valid on macOS + exFAT
I’m reporting this to prevent false negatives and unnecessary device returns.
When running F3 on macOS with exFAT-formatted devices, the tool may report systematic data corruption (typically exactly one cluster, e.g. 128 KB = 256 sectors) even on brand-new, healthy storage.
After extensive investigation, this appears to be a tool–OS–filesystem semantic mismatch, not actual media corruption.
This issue does not reproduce on:
APFS (macOS)
Linux (ext4 / exFAT)
Repeated runs on the same device (often disappears)
Observed Symptoms
Typical output from
f3readon macOS + exFAT:Exactly one missing or corrupted cluster
Often 128 KB (256 sectors)
Reported as corrupted or overwritten
More visible on HDDs or slower devices
Example:
Corrupted: 128.00 KB (256 sectors)exfat fs default cluster = 128KiB (256 sectors)
Root Cause Analysis
Key point
This is a documented semantic difference from Linux.
What F3 currently does (simplified)
write(...) fsync(fd) posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED)What happens on macOS + exFAT
write()populates the page cachefsync()flushes known dirty pages, but:The last cluster (commonly one exFAT cluster = 128 KB) may still be pending
POSIX_FADV_DONTNEEDaggressively discards page cacheOn subsequent
read():data is reloaded from disk
but the last cluster may contain:
old data
zeroes
uninitialized content
👉 Result: exactly one missing cluster, consistently aligned to exFAT cluster size.
This is not a block alignment issue, not an ioctl issue, and not a hardware failure.
Why APFS Does Not Show This Problem
APFS uses:
Copy-on-write
Transactional block allocation + data + metadata updates
fsync()commits the whole transactionTherefore, F3’s assumption:
happens to hold on APFS, but does not hold on exFAT.
Why This Is Not an exFAT “Bug”
exFAT:
Has no journaling
Has weak ordering guarantees
Relies on cooperative cache behavior
macOS’s exFAT driver prioritizes performance and allows delayed allocation.
The behavior is legal under POSIX and macOS semantics.
Why This Is Dangerous
Users may falsely conclude:
“My new SD card is defective”
“The device has bad sectors”
Especially harmful for:
camera media
large-capacity cards
HDD-based storage
In reality, the data may never have been written incorrectly at all.
Recommended Fixes
Option 1 (Best): Use macOS-specific full sync
On macOS, replace
fsync()with:fcntl(fd, F_FULLFSYNC)This guarantees data reaches physical media.
Option 2: Remove
POSIX_FADV_DONTNEEDon macOS + exFATAvoid dropping page cache immediately after
fsync()on macOS.Option 3: Document the limitation clearly
At minimum, warn users:
Summary
This is not hardware corruption
This is not block misalignment
This is a filesystem + OS semantic mismatch
F3’s assumptions are valid on Linux and APFS
They are not valid on macOS + exFAT
I’m reporting this to prevent false negatives and unnecessary device returns.