Skip to content

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

Merged
hbirth merged 4 commits into
redfs-ubuntu-hwe-6.17.0-16.16-24.04.1from
fix-redfs-6.17-iomap-write-dlm-eagain-eio
Jun 11, 2026
Merged

Fix cached write with an incomplete page when DLM return -EAGAIN#149
hbirth merged 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

@bsbernd bsbernd commented May 1, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

@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

@hbirth hbirth left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@hbirth

hbirth commented May 2, 2026

Copy link
Copy Markdown
Collaborator

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

@bsbernd bsbernd force-pushed the fix-redfs-6.17-iomap-write-dlm-eagain-eio branch 2 times, most recently from 356e809 to 5bb799c Compare May 2, 2026 11:56
@hbirth

hbirth commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

@bsbernd is there more to be done here ... this looks mergeable to me

@bsbernd

bsbernd commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator Author

@hbirth I think we can merge it, although I just see that there is a merge conflict. Will look into it in the evening.

@hbirth

hbirth commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Yes, seen that. I can fix that, too ... just tell me

@bsbernd

bsbernd commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator Author

As you want

@hbirth

hbirth commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

OK ... I'll fix the merge conflict and merge ... since 'somebody' wants to enable writeback in 6.17

hbirth and others added 4 commits June 11, 2026 11:40
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>
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>
@hbirth hbirth force-pushed the fix-redfs-6.17-iomap-write-dlm-eagain-eio branch from 5bb799c to 7e0d50a Compare June 11, 2026 09:42
@hbirth hbirth merged commit 975dffc into redfs-ubuntu-hwe-6.17.0-16.16-24.04.1 Jun 11, 2026
2 checks passed
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