Dear f2fs Development Community,

This thread is initiated to discuss the challenge of integrating
iomap_folio_state (hereafter referred to as ifs) into f2fs pointed out
by Mr. Matthew in this email:
https://lore.kernel.org/linux-f2fs-devel/camlch1eosva1as4vdbcpsh75apfmknofhihorxvommz-+mu...@mail.gmail.com/T/#t

> The challenge with that is that iomap does not support all the
> functionality that f2fs requires.  The iomap data structure could
> be duplicated inside f2fs, but then we hit the problem that f2fs
> currently stores other information in folio->private.  So we'd need
> to add a flags field to iomap_folio_state to store that information
> instead.


To address this, I have designed a custom structure for f2fs, aiming
to minimize modifications to existing iomap functionalities and data
structures. The proposed structure, named f2fs_iomap_folio_state
(hereafter referred to as f2fs_ifs), is defined as follows:

f2fs_iomap_folio_state
{
    struct iomap_folio_state ifs;
    unsigned int magic_number;
    unsigned int private; // for f2fs page private flags
}

The f2fs_ifs structure embeds the standard ifs structure at the
beginning of its definition. This ensures that the initial memory
layout of f2fs_ifs is identical to ifs, thereby maintaining
compatibility with a wide range of iomap APIs (excluding ifs_alloc and
ifs_free). Importantly, calling ifs_alloc on a folio whose
folio->private already points to an f2fs_ifs structure will not result
in errors. This is because ifs_alloc is designed to return the
existing pointer if folio->private is not NULL.

My original purpose behind this design is to preserve the integrity of
native iomap functions and data structures as much as possible. The
level of customization currently provided by iomap functions for file
systems appears to be insufficient for f2fs's requirements. For
example, the iomap_readahead function's iomap_readpage_iter internally
and inflexibly calls APIs like ifs_alloc.

Currently, there are two key technical details that require careful
consideration:

Distinguishing between ifs and f2fs_ifs: A significant challenge is
reliably differentiating whether a given folio->private pointer points
to a standard ifs or our custom f2fs_ifs structure. This is a headache
as it involves runtime type identification from a void*, which cannot
be resolved through compile-time type checking. To mitigate this, I
have introduced a magic_number field within f2fs_ifs. The proposed
approach is to cast folio->private to f2fs_ifs, calculate an offset
based on the size of the ifs structure (which is dynamically
determined by the folio's block count due to the variable-sized state
bitmap in ifs), and then check if the value at the magic_number field
matches a pre-defined magic value. If a match is found, we infer that
it is an f2fs_ifs.

However, this approach is not without risk. In the scenario where
folio->private points to a regular ifs, and by a little chance, the
value at the calculated offset within the ifs structure happens to
coincide with our chosen magic number, the check would incorrectly
identify it as f2fs_ifs. This could potentially lead to undefined
behavior. I am actively seeking more robust solutions for this type
identification problem and would greatly appreciate any suggestions or
alternative approaches the community might offer.

Allocation Timing of f2fs_ifs: Another crucial aspect is determining
the optimal timing for allocating f2fs_ifs. My current thinking is
that allocating it during the readahead process might be advantageous.
At this stage, the folio is under lock protection, ensuring thread
safety. Furthermore, allocating f2fs_ifs during readahead could
ideally ensure that the private field of all folios within the page
cache consistently points to f2fs_ifs.I belive this will bring a lot
of convenience.
The implementation may be a bit tricky. If we intend to leverage
iomap_readahead to provide an iomap-based readahead function for f2fs,
custom iomap_begin and iomap_end operations will not suffice for
allocating f2fs_ifs. This limitation arises because these functions do
not have access to the necessary readahead_control and
iomap_readpage_ctx structures, and consequently, cannot directly
access the folio.

My current proposed solution is as follows:

f2fs_iomap_readahead(readahead_control* rac)
{
    struct readahead_control rac_cp = copy_rac(rac);
    struct folio* folio;
    while (folio = readahead_folio(rac_cp)) {
        f2fs_ifs_alloc(folio);
    }
    iomap_readahead(rac, &f2fs_buffered_read_iomap_ops);
}

Alternatively, we could consider duplicating the iomap_readahead
function within f2fs and making the necessary modifications directly
within the duplicated code.

I would greatly appreciate any feedback, insights, and suggestions
from the community regarding these technical details and the overall
approach. Your expertise and perspectives are invaluable as we work
towards a robust and efficient integration of iomap_folio_state into
f2fs.

Thank you for your time and consideration.


_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to