ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_fs_fat_space.c File Reference

Free / used / total space query (ra8_fs_free_space()) for FAT and exFAT. More...

#include <stddef.h>
#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_fs.h"
#include "ra8_fs_fat_internal.h"
#include "ra8_fs_meta.h"
Include dependency graph for ra8_fs_fat_space.c:

Go to the source code of this file.

Enumerations

enum  ra8_fs_space_const_t : uint32_t {
  k_space_bits_per_byte = 8U ,
  k_space_bit_mask = 7U ,
  k_space_byte_shift = 3U
}
 Bit-arithmetic constants for the free-space walkers. More...

Functions

static uint32_t internal_popcount8 (uint8_t b)
 Count the set bits in one byte.
static ra8_err_t internal_space_fat_free (const ra8_fs_mount_t *m, uint32_t *out_free)
 Count free clusters on a FAT12/16/32 volume by scanning the FAT.
static ra8_err_t internal_space_exfat_free (const ra8_fs_mount_t *m, uint32_t *out_free)
 Count free clusters on an exFAT volume by population-counting the bitmap.
static ra8_err_t internal_space_free_clusters (const ra8_fs_mount_t *m, uint32_t *out_free)
 Resolve the free-cluster count: cached, or freshly walked and cached.
static ra8_err_t internal_space_locked (const ra8_fs_mount_t *handle, ra8_fs_space_t *out)
 Report free/used/total space – the guarded body of ra8_fs_free_space().
ra8_err_t ra8_fs_free_space (const ra8_fs_mount_t *handle, ra8_fs_space_t *out)
 Report a mounted volume's total, free, and used space.

Detailed Description

Free / used / total space query (ra8_fs_free_space()) for FAT and exFAT.

"How much room is left" answered from counts the driver already keeps. On a FAT32 volume whose FSInfo validated at mount the free-cluster count is the cached one, reported in O(1); on FAT12/FAT16, or a FAT32 whose FSInfo was absent or untrusted, the FAT is scanned once (through the shared one-sector FAT cache, so a full scan costs one read per 128/256 clusters, not one per cluster) and the result is cached for the next query. On exFAT the allocation bitmap – which exFAT spec sec 7.1 makes the sole authority for allocation state – is population-counted, also cached.

Byte totals are 64-bit: a 2 TiB volume's byte count overflows 32 bits even though FAT file sizes stay 32-bit. The cluster counts stay 32-bit, matching the on-disk fields they come from.

References (every shorthand citation in this file):

  • "MS FAT spec" = Microsoft Corp., "FAT: General Overview of On-Disk Format", v1.03, December 6 2000.
  • "exFAT spec" = Microsoft Corp., "exFAT file system specification", revision 1.00.

NASA Power-of-Ten compliance:

  • Rule 2: the FAT scan is bounded by count_of_clusters; the bitmap scan by the bitmap's own byte length (itself <= count_of_clusters / 8).
  • Rule 3: zero malloc; one 512-byte sector buffer on the stack.
  • Rule 7: every backend call is checked.
Since
0.1.0

Definition in file ra8_fs_fat_space.c.

Enumeration Type Documentation

◆ ra8_fs_space_const_t

enum ra8_fs_space_const_t : uint32_t

Bit-arithmetic constants for the free-space walkers.

The exFAT allocation bitmap packs one cluster per bit, LSB first, so a cluster index divides by 8 (shift 3) to a byte and masks with 7 to a bit – the same layout the exFAT mutation helpers use.

Invariant
k_space_bit_mask + 1 == 1 << k_space_byte_shift == k_space_bits_per_byte.
Since
0.1.0
Enumerator
k_space_bits_per_byte 

Bits in one allocation-bitmap byte.

k_space_bit_mask 

Cluster index -> bit within its byte.

k_space_byte_shift 

log2(8): cluster index -> bitmap byte.

Definition at line 55 of file ra8_fs_fat_space.c.

Function Documentation

◆ internal_popcount8()

uint32_t internal_popcount8 ( uint8_t b)
static

Count the set bits in one byte.

A bounded eight-iteration population count – no compiler builtin, so the same result on the host and on the Cortex-M target regardless of __builtin_popcount availability.

Parameters
[in]bByte to count.
Returns
The number of 1 bits in b.
Return values
0..8The population count.
Precondition
None (total over uint8_t).
b is a whole byte.
Postcondition
No state modified.
The result is at most 8.
Note
Pure function; trivially thread-safe.
Bounded loop (NASA Rule 2): exactly k_space_bits_per_byte iterations.
Since
0.1.0

Definition at line 84 of file ra8_fs_fat_space.c.

References k_space_bits_per_byte.

Referenced by internal_space_exfat_free().

◆ internal_space_exfat_free()

ra8_err_t internal_space_exfat_free ( const ra8_fs_mount_t * m,
uint32_t * out_free )
static

Count free clusters on an exFAT volume by population-counting the bitmap.

Locates the allocation bitmap (exFAT spec sec 7.1.5), reads it sector by sector through one reused buffer, and sums the SET bits over the volume's count_of_clusters cluster bits – the used count. Free is the complement. The final partial byte is masked to the volume's last cluster so bits past the cluster heap (which the spec leaves 0, but a defensive read cannot assume) never inflate the used count.

Parameters
[in]mMounted exFAT volume.
[out]out_freeReceives the free-cluster count.
Returns
Error code.
Return values
k_ra8_okout_free holds the count.
k_ra8_err_not_foundNo allocation-bitmap entry (corrupt volume).
k_ra8_err_*Backend read failure.
Precondition
m and out_free are non-NULL; m->type is exFAT.
The mount's geometry is populated.
Postcondition
On success out_free is <= m->count_of_clusters.
No volume state is modified.
Note
Bounded loop (NASA Rule 2): count_of_clusters / 8 + 1 iterations.
Not thread-safe; callers serialise filesystem operations.
Since
0.1.0

Definition at line 166 of file ra8_fs_fat_space.c.

References ra8_fs_mount_t::count_of_clusters, internal_popcount8(), k_ra8_ok, k_space_bit_mask, k_space_byte_shift, priv_bps(), priv_cluster_to_lba(), priv_exfat_find_bitmap(), priv_read_sector(), and priv_sec_io().

Referenced by internal_space_free_clusters().

◆ internal_space_fat_free()

ra8_err_t internal_space_fat_free ( const ra8_fs_mount_t * m,
uint32_t * out_free )
static

Count free clusters on a FAT12/16/32 volume by scanning the FAT.

Reads every data cluster's FAT entry through priv_fat_get (and so through the shared one-sector FAT cache) and counts the ones that read as k_cluster_free. The fallback for a volume with no trusted FSInfo count; the result is cached by the caller.

Parameters
[in]mMounted FAT volume.
[out]out_freeReceives the free-cluster count.
Returns
Error code.
Return values
k_ra8_okout_free holds the count.
k_ra8_err_*Backend read failure mid-scan.
Precondition
m and out_free are non-NULL; m->type is FAT12/16/32.
The mount's geometry is populated.
Postcondition
On success out_free is <= m->count_of_clusters.
No volume state is modified.
Note
Bounded loop (NASA Rule 2): m->count_of_clusters iterations.
Not thread-safe; callers serialise filesystem operations.
Since
0.1.0

Definition at line 119 of file ra8_fs_fat_space.c.

References ra8_fs_mount_t::count_of_clusters, k_cluster_first_data, k_cluster_free, k_ra8_ok, and priv_fat_get().

Referenced by internal_space_free_clusters().

◆ internal_space_free_clusters()

ra8_err_t internal_space_free_clusters ( const ra8_fs_mount_t * m,
uint32_t * out_free )
static

Resolve the free-cluster count: cached, or freshly walked and cached.

On the FAT variants it prefers the allocator's tracked count (FAT32 FSInfo, or a FAT12/16 count this routine cached earlier): the FAT allocator keeps it current on every priv_alloc_cluster / priv_free_chain, so once known it stays right. When that count is k_fs_free_unknown the FAT is walked once and the result cached.

exFAT is the exception and is ALWAYS recomputed. Its allocator maintains the allocation bitmap directly and never touches the tracked free count, so a cached value would go stale on the next write; the bitmap is authoritative and small, so a fresh population count every query is both correct and cheap.

Parameters
[in]mMounted volume.
[out]out_freeReceives the free-cluster count.
Returns
Error code.
Return values
k_ra8_okout_free holds the count.
k_ra8_err_*Backend read failure while walking.
Precondition
m and out_free are non-NULL; the mount is in use.
The mount's geometry is populated.
Postcondition
On success out_free is <= m->count_of_clusters.
On a fresh FAT walk the count is cached in the allocator slot.
Note
Not thread-safe; callers serialise filesystem operations.
Since
0.1.0

Definition at line 241 of file ra8_fs_fat_space.c.

References internal_space_exfat_free(), internal_space_fat_free(), k_fs_free_unknown, k_ra8_fs_type_exfat, k_ra8_ok, priv_free_count_cache(), priv_free_count_peek(), and ra8_fs_mount_t::type.

Referenced by internal_space_locked().

◆ internal_space_locked()

ra8_err_t internal_space_locked ( const ra8_fs_mount_t * handle,
ra8_fs_space_t * out )
static

Report free/used/total space – the guarded body of ra8_fs_free_space().

Resolves the free-cluster count, clamps it to the volume size (a corrupt count above the disk size is worse than a walk), and scales the cluster figures by the allocation-unit size into the 64-bit byte totals. The public ra8_fs_free_space brackets this with the library lock; the full contract is documented there.

Parameters
[in]handleMount handle.
[out]outReceives the space figures.
Returns
Error code.
Return values
k_ra8_okFigures reported.
k_ra8_err_null_ptrhandle or out is NULL.
k_ra8_err_invalid_stateMount is not in use.
k_ra8_err_*Backend read failure.
Precondition
The library lock is held (or none is installed).
handle and out are non-NULL.
Postcondition
On success out->used_clusters + out->free_clusters == out->total_clusters.
No volume state is modified.
Note
Never call this from outside ra8_fs; it is the unlocked half.
The null-pointer guard's MC/DC vectors live in test_ra8_fs_space.c (test_space_null_guard).
Since
0.1.0

Definition at line 290 of file ra8_fs_fat_space.c.

References internal_space_free_clusters(), internal_space_locked(), k_ra8_err_null_ptr, k_ra8_ok, and priv_cluster_bytes().

Referenced by internal_space_locked(), and ra8_fs_free_space().

◆ ra8_fs_free_space()

ra8_err_t ra8_fs_free_space ( const ra8_fs_mount_t * handle,
ra8_fs_space_t * out )
nodiscard

Report a mounted volume's total, free, and used space.

Answers "how much room is left" from the counts the driver already keeps. On FAT32 whose FSInfo validated at mount the free count is the cached one (O(1)); otherwise – FAT12/FAT16, or a FAT32 whose FSInfo was absent or untrusted – the FAT is walked once and the result is cached for subsequent queries. On exFAT the allocation bitmap (which alone is authoritative for allocation state) is population-counted, also cached. The byte totals are the cluster counts scaled by the allocation-unit size, so a caller can compare bytes directly without knowing the cluster geometry.

Parameters
[in]handleMount handle from ra8_fs_mount().
[out]outReceives the capacity / free / used figures on success.
Returns
ra8_err_t Error code.
Return values
k_ra8_okFigures reported in out.
k_ra8_err_null_ptrhandle or out is NULL.
k_ra8_err_invalid_stateMount is not in use.
k_ra8_err_*Backend read failure while walking the FAT or the allocation bitmap.
Precondition
handle and out are non-NULL.
Mount is in use.
Postcondition
On k_ra8_ok out->used_clusters + out->free_clusters == out->total_clusters and the byte totals equal the cluster totals scaled by out->bytes_per_cluster.
No volume state is modified.
Note
Not thread-safe unless a lock is installed (see ra8_fs_set_lock()).
See also
ra8_fs_space_t
Since
0.1.0

Definition at line 327 of file ra8_fs_fat_space.c.

References internal_space_locked(), priv_lock_acquire(), priv_lock_release(), and ra8_fs_free_space().

Referenced by internal_native_free_space(), and ra8_fs_free_space().