Skip to content

Fix cached write with an incomplete page when DLM return -EAGAIN#149

Open
bsbernd wants to merge 4 commits into
redfs-ubuntu-hwe-6.17.0-16.16-24.04.1from
fix-redfs-6.17-iomap-write-dlm-eagain-eio
Open

Fix cached write with an incomplete page when DLM return -EAGAIN#149
bsbernd wants to merge 4 commits into
redfs-ubuntu-hwe-6.17.0-16.16-24.04.1from
fix-redfs-6.17-iomap-write-dlm-eagain-eio

Conversation

@bsbernd
Copy link
Copy Markdown
Collaborator

@bsbernd bsbernd commented May 1, 2026

No description provided.

Fix a logical error where the DLM lock was acquired regardless
of whether the writeback part was actually called.
This is necessarry after the move to  iomap_file_buffered_write()

Signed-off-by: Horst Birthelmer <hbirthelmer@ddn.com>
@bsbernd bsbernd requested review from cding-ddn, hbirth and yongzech May 1, 2026 20:42
@bsbernd bsbernd force-pushed the fix-redfs-6.17-iomap-write-dlm-eagain-eio branch from 33307fa to 849ee2b Compare May 1, 2026 20:59
hbirth
hbirth previously approved these changes May 2, 2026
Copy link
Copy Markdown
Collaborator

@hbirth hbirth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@hbirth
Copy link
Copy Markdown
Collaborator

hbirth commented May 2, 2026

@bsbernd not merging until you tell me to ;-)

@bsbernd bsbernd force-pushed the fix-redfs-6.17-iomap-write-dlm-eagain-eio branch from 849ee2b to 356e809 Compare May 2, 2026 07:26
hbirth and others added 3 commits May 2, 2026 09:45
fuse_do_readfolio() is called by fuse_iomap_read_folio_range()
as well and is not supposed to return a positive value, thus
the translation has to be done in another layer.

Signed-off-by: Horst Birthelmer <hbirthelmer@ddn.com>
When the FUSE server returns -EAGAIN during write-back operations
(signaled by DLM), the write fails with an IO error. This happens
because:

1. Page invalidation holds DLM lock and needs folio lock
2. iomap write path holds folio lock and calls fuse_iomap_read_folio_range()
3. FUSE gets -EAGAIN from server (cannot acquire DLM lock - would deadlock)
4. fuse_do_readfolio() converts -EAGAIN to AOP_TRUNCATED_PAGE and unlocks folio
   (This prevents the deadlock by releasing the folio lock)
5. However, iomap doesn't understand AOP_TRUNCATED_PAGE and treats it as error
6. Result: Write fails with IO error, even though it's just temporary contention

This is a FUSE-only workaround until mainline iomap gains
AOP_TRUNCATED_PAGE retry support. The solution:

1. Stack-allocate retry state in fuse_cache_write_iter()
2. Register it in fuse_conn xarray before calling iomap (indexed by task pointer)
3. When fuse_iomap_read_folio_range() sees AOP_TRUNCATED_PAGE:
   - Mark the retry flag in the registered state
   - Convert to -EAGAIN for iomap
4. After iomap returns, check the retry flag
5. If set, retry the entire write operation
6. Remove from xarray when done (or keep for next retry iteration)

This allows writes to succeed by retrying after the DLM lock contention
clears, rather than failing with IO error.

Technical flow showing why iov_iter is not advanced on -EAGAIN:

fuse_cache_write_iter()
  total_written = 0
retry:
  iomap_file_buffered_write()
    iomap_write_iter() [write loop]
      iomap_write_begin()
        __iomap_write_begin()
          Need read? → Yes
            read_folio_range()
              FUSE server -EAGAIN?
                Yes → Set retry flag, return -EAGAIN
                No → Success
            Error → Break loop [iov_iter NOT advanced]
            Success → Continue
      copy_folio_from_iter_atomic() [Advances iov_iter]
      iomap_write_end()
      Advance iter.pos
      Loop while more data
    Update iocb->ki_pos = iter.pos
    Return bytes written

  if (written > 0)
    total_written += written

  if (retry_needed)
    goto retry

  return total_written

Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
-EAGAIN is semantically overloaded for a DLM error and not
self describing, switch to -EDEADLK.
In order to allow a graceful daemon change, -EAGAIN is kept for now.

Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
@bsbernd bsbernd force-pushed the fix-redfs-6.17-iomap-write-dlm-eagain-eio branch from 356e809 to 5bb799c Compare May 2, 2026 11:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants