bfd: fix partial write handling in bwritev()#2975
bfd: fix partial write handling in bwritev()#29753idey wants to merge 1 commit intocheckpoint-restore:criu-devfrom
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## criu-dev #2975 +/- ##
============================================
- Coverage 57.76% 57.12% -0.64%
============================================
Files 142 154 +12
Lines 37664 40326 +2662
Branches 0 8845 +8845
============================================
+ Hits 21758 23038 +1280
- Misses 15906 17028 +1122
- Partials 0 260 +260 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR hardens CRIU’s bfd unbuffered write path to ensure bwritev() reliably writes the full iovec payload (retrying writev() as needed), preventing incomplete checkpoint images due to partial writev() results.
Changes:
- Add
bfd_writev_all()helper to retrywritev()until all iovecs are consumed or an error occurs. - In unbuffered
bwritev(), duplicate the iovec array so progress-tracking modifications don’t affect the caller’s iovecs. - Return early for
cnt == 0and treatwritev()returning 0 as an error to avoid no-progress loops.
b11037d to
b2230a8
Compare
|
@avagin Could you please take a look at this? |
c675610 to
18de5f8
Compare
3ccf9c8 to
52a8ef9
Compare
When bfd is unbuffered, bwritev() used writev() directly, which can return partial writes and leave checkpoint images incomplete. Fix this by retrying writev() until all iovecs are written or an error occurs. Temporarily modify the first iovec's base and length to track progress on partial writes, then restore it before the next iteration. Changes the function signature to accept non-const iovec, as we need to modify it to track progress (same pattern as write_all() with buffers). Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
8366a67 to
ca472b8
Compare
|
@avagin updated! let me know if this looks good to you. |
| * bytes from previous partial writes, then restore it before | ||
| * the next iteration. | ||
| */ | ||
| iov[0].iov_base = (char *)iov[0].iov_base + off; |
There was a problem hiding this comment.
why do you need to convert it to (char *)?
|
|
||
| written += ret; | ||
| while (ret) { | ||
| if (iov[0].iov_len > ret) { |
There was a problem hiding this comment.
I think here is a bug. we adjusted iov_len after the write syscall. We probably need to do ret += off before this loop.
When bfd is unbuffered, bwritev() used writev() directly, which can return partial writes and leave checkpoint images incomplete.
This patch fixes this by ensuring writev() is retried until all iovecs are fully written or an error occurs.
Changes:
constfrom theiovparameter inbwritev()(and updates the header) to allow direct pointer manipulation.iov_baseandiov_lenof the current iovec and advancing theiovpointer andcntas data is successfully written.