mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-23 01:59:04 +00:00
bfd: fix partial write handling in bwritev()
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>
This commit is contained in:
parent
b99cbc1e8c
commit
d2caebfd4e
2 changed files with 42 additions and 7 deletions
47
criu/bfd.c
47
criu/bfd.c
|
|
@ -321,16 +321,51 @@ int bwrite(struct bfd *bfd, const void *buf, int size)
|
|||
return __bwrite(bfd, buf, size);
|
||||
}
|
||||
|
||||
int bwritev(struct bfd *bfd, const struct iovec *iov, int cnt)
|
||||
int bwritev(struct bfd *bfd, struct iovec *iov, int cnt)
|
||||
{
|
||||
int i, written = 0;
|
||||
|
||||
if (!bfd_buffered(bfd)) {
|
||||
/*
|
||||
* FIXME writev() should be called again if writev() writes
|
||||
* less bytes than requested.
|
||||
*/
|
||||
return writev(bfd->fd, iov, cnt);
|
||||
size_t off = 0;
|
||||
|
||||
while (cnt) {
|
||||
ssize_t ret;
|
||||
|
||||
/*
|
||||
* Temporarily modify the first iovec to skip already-written
|
||||
* bytes from previous partial writes, then restore it before
|
||||
* the next iteration.
|
||||
*/
|
||||
iov[0].iov_base += off;
|
||||
iov[0].iov_len -= off;
|
||||
ret = writev(bfd->fd, iov, cnt);
|
||||
iov[0].iov_base -= off;
|
||||
iov[0].iov_len += off;
|
||||
if (ret < 0) {
|
||||
pr_perror("writev failed for fd %d", bfd->fd);
|
||||
return ret;
|
||||
}
|
||||
if (ret == 0) {
|
||||
errno = EIO;
|
||||
pr_perror("writev made no progress (fd %d)", bfd->fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
written += ret;
|
||||
ret += off;
|
||||
while (ret) {
|
||||
if (iov[0].iov_len > ret) {
|
||||
off = ret;
|
||||
break;
|
||||
}
|
||||
ret -= iov[0].iov_len;
|
||||
iov++;
|
||||
cnt--;
|
||||
off = 0;
|
||||
}
|
||||
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ char *breadline(struct bfd *f);
|
|||
char *breadchr(struct bfd *f, char c);
|
||||
int bwrite(struct bfd *f, const void *buf, int sz);
|
||||
struct iovec;
|
||||
int bwritev(struct bfd *f, const struct iovec *iov, int cnt);
|
||||
int bwritev(struct bfd *f, struct iovec *iov, int cnt);
|
||||
int bread(struct bfd *f, void *buf, int sz);
|
||||
int bfd_flush_images(void);
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue