plugins/amdgpu: Convert away from libc buffered file IO

Currently the code contains multiple places where callers expect the errno
to be valid (implied by calling pr_perror to log file IO errors) after
calling open_img_file(), read_fp() and write_fp() helpers. Problem there
is that those helpers can destroy the errno courtesy of themselves
emitting log messages via fprintf.

Furthermore, the callers then sometimes invent the errors to return back
to the caller, or even outside of the plugin.

On top of that there is no benefit to buffered file IO given the plugin
reads and writes in buffer object size chunks, so it it preferrable to
just go direct and avoid any possibility of extra copying to and from libc
temporary buffers.

So lets just convert it all in one swoop to POSIX IO and make sure correct
errnos are always propagated to the caller (including to CRIU core).

Hopefully this removes all instances of incorrect pr_perror log messages.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com> # v1
---
v2:
 * Handle short reads and writes.
 * Add O_TRUNC.

v3:
 * Handle EINTR and EAGAIN.
 * Set errno on len == 0.
 * Use %zu for size_t printing.

v4:
 * Drop shadowed ret.
 * Drop needless casts.
This commit is contained in:
Tvrtko Ursulin 2026-02-19 17:05:59 +00:00 committed by Andrei Vagin
parent 909eb890f0
commit 9a65f7ede6
5 changed files with 159 additions and 153 deletions

View file

@ -551,7 +551,7 @@ void free_and_unmap(uint64_t size, amdgpu_bo_handle h_bo, amdgpu_va_handle h_va,
amdgpu_bo_free(h_bo);
}
int sdma_copy_bo(int shared_fd, uint64_t size, FILE *storage_fp,
int sdma_copy_bo(int shared_fd, uint64_t size, int storage_fd,
void *buffer, size_t buffer_size, amdgpu_device_handle h_dev,
uint64_t max_copy_size, enum sdma_op_type type, bool do_not_free)
{
@ -676,7 +676,8 @@ int sdma_copy_bo(int shared_fd, uint64_t size, FILE *storage_fp,
memset(ib, 0, packets_per_buffer * 28);
if (type == SDMA_OP_VRAM_WRITE) {
err = read_fp(storage_fp, buffer, min(bytes_remain, buffer_bo_size));
err = img_read(storage_fd, buffer,
min(bytes_remain, buffer_bo_size));
if (err) {
pr_perror("failed to read from storage");
goto err_bo_list;
@ -752,7 +753,8 @@ int sdma_copy_bo(int shared_fd, uint64_t size, FILE *storage_fp,
}
if (type == SDMA_OP_VRAM_READ) {
err = write_fp(storage_fp, buffer, buffer_bo_size - buffer_space_remain);
err = img_write(storage_fd, buffer,
buffer_bo_size - buffer_space_remain);
if (err) {
pr_perror("failed to write out to storage");
goto err_cs_submit_ib;
@ -806,11 +808,11 @@ void *dump_bo_contents(void *_thread_data)
struct amdgpu_gpu_info gpu_info = { 0 };
amdgpu_device_handle h_dev;
size_t max_bo_size = 0, image_size = 0, buffer_size;
int bo_contents_fd = -1;
uint64_t max_copy_size;
uint32_t major, minor;
int num_bos = 0;
int i, ret = 0;
FILE *bo_contents_fp = NULL;
void *buffer = NULL;
char img_path[40];
@ -851,10 +853,9 @@ void *dump_bo_contents(void *_thread_data)
}
snprintf(img_path, sizeof(img_path), IMG_KFD_PAGES_FILE, thread_data->id, thread_data->gpu_id);
bo_contents_fp = open_img_file(img_path, true, &image_size, true);
if (!bo_contents_fp) {
pr_perror("Cannot fopen %s", img_path);
ret = -EIO;
bo_contents_fd = open_img_file(img_path, true, &image_size, true);
if (bo_contents_fd < 0) {
ret = bo_contents_fd;
goto exit;
}
@ -868,8 +869,9 @@ void *dump_bo_contents(void *_thread_data)
num_bos++;
/* perform sDMA based vram copy */
ret = sdma_copy_bo(bo_buckets[i].dmabuf_fd, bo_buckets[i].size, bo_contents_fp, buffer, buffer_size, h_dev, max_copy_size,
SDMA_OP_VRAM_READ, false);
ret = sdma_copy_bo(bo_buckets[i].dmabuf_fd, bo_buckets[i].size,
bo_contents_fd, buffer, buffer_size, h_dev,
max_copy_size, SDMA_OP_VRAM_READ, false);
if (ret) {
pr_err("Failed to drain the BO using sDMA: bo_buckets[%d]\n", i);
@ -880,8 +882,8 @@ void *dump_bo_contents(void *_thread_data)
exit:
pr_info("Thread[0x%x] done num_bos:%d ret:%d\n", thread_data->gpu_id, num_bos, ret);
if (bo_contents_fp)
fclose(bo_contents_fp);
if (bo_contents_fd >= 0)
close(bo_contents_fd);
xfree(buffer);
@ -898,9 +900,9 @@ void *restore_bo_contents(void *_thread_data)
size_t image_size = 0, total_bo_size = 0, max_bo_size = 0, buffer_size;
struct amdgpu_gpu_info gpu_info = { 0 };
amdgpu_device_handle h_dev;
int bo_contents_fd = -1;
uint64_t max_copy_size;
uint32_t major, minor;
FILE *bo_contents_fp = NULL;
void *buffer = NULL;
char img_path[40];
int num_bos = 0;
@ -924,10 +926,9 @@ void *restore_bo_contents(void *_thread_data)
SDMA_LINEAR_COPY_MAX_SIZE - 1;
snprintf(img_path, sizeof(img_path), IMG_KFD_PAGES_FILE, thread_data->id, thread_data->gpu_id);
bo_contents_fp = open_img_file(img_path, false, &image_size, true);
if (!bo_contents_fp) {
pr_perror("Cannot fopen %s", img_path);
ret = -errno;
bo_contents_fd = open_img_file(img_path, false, &image_size, true);
if (bo_contents_fd < 0) {
ret = bo_contents_fd;
goto exit;
}
@ -967,8 +968,9 @@ void *restore_bo_contents(void *_thread_data)
num_bos++;
ret = sdma_copy_bo(bo_buckets[i].dmabuf_fd, bo_buckets[i].size, bo_contents_fp, buffer, buffer_size, h_dev, max_copy_size,
SDMA_OP_VRAM_WRITE, false);
ret = sdma_copy_bo(bo_buckets[i].dmabuf_fd, bo_buckets[i].size,
bo_contents_fd, buffer, buffer_size, h_dev,
max_copy_size, SDMA_OP_VRAM_WRITE, false);
if (ret) {
pr_err("Failed to fill the BO using sDMA: bo_buckets[%d]\n", i);
break;
@ -978,8 +980,8 @@ void *restore_bo_contents(void *_thread_data)
exit:
pr_info("Thread[0x%x] done num_bos:%d ret:%d\n", thread_data->gpu_id, num_bos, ret);
if (bo_contents_fp)
fclose(bo_contents_fp);
if (bo_contents_fd >= 0)
close(bo_contents_fd);
xfree(buffer);
@ -1003,9 +1005,7 @@ int check_hsakmt_shared_mem(uint64_t *shared_mem_size, uint32_t *shared_mem_magi
/* First 4 bytes of shared file is the magic */
ret = read_file(HSAKMT_SHM_PATH, shared_mem_magic, sizeof(*shared_mem_magic));
if (ret)
pr_perror("Failed to read shared mem magic");
else
if (!ret)
pr_debug("Shared mem magic:0x%x\n", *shared_mem_magic);
return 0;
@ -1124,15 +1124,12 @@ int amdgpu_id_for_handle(int handle)
static int load_img(char *filename, unsigned char **out_buf, size_t *out_len)
{
unsigned char *buf;
FILE *img_fp;
int fd, ret;
size_t len;
int ret;
img_fp = open_img_file(filename, false, &len, true);
if (!img_fp) {
ret = -ENOENT;
goto out;
}
fd = open_img_file(filename, false, &len, true);
if (fd < 0)
return fd;
buf = xmalloc(len);
if (!buf) {
@ -1140,7 +1137,7 @@ static int load_img(char *filename, unsigned char **out_buf, size_t *out_len)
goto out_close;
}
ret = read_fp(img_fp, buf, len);
ret = img_read(fd, buf, len);
if (ret) {
xfree(buf);
} else {
@ -1149,11 +1146,7 @@ static int load_img(char *filename, unsigned char **out_buf, size_t *out_len)
}
out_close:
fclose(img_fp);
out:
if (ret < 0)
pr_err("Unable to read from %s", filename);
close(fd);
return ret;
}
@ -1973,7 +1966,7 @@ int amdgpu_plugin_restore_file(int id, bool *retry_needed)
CriuKfd *e = NULL;
struct kfd_ioctl_criu_args args = { 0 };
size_t img_size;
FILE *img_fp = NULL;
int img_fd;
*retry_needed = false;
@ -1984,8 +1977,8 @@ int amdgpu_plugin_restore_file(int id, bool *retry_needed)
snprintf(img_path, sizeof(img_path), IMG_KFD_FILE, id);
img_fp = open_img_file(img_path, false, &img_size, false);
if (!img_fp)
img_fd = open_img_file(img_path, false, &img_size, false);
if (img_fd < 0)
return amdgpu_plugin_restore_drm_file(id, retry_needed);
fd = open(AMDGPU_KFD_DEVICE, O_RDWR | O_CLOEXEC);
@ -2002,19 +1995,18 @@ int amdgpu_plugin_restore_file(int id, bool *retry_needed)
pr_info("KFD Image file size:%ld\n", img_size);
buf = xmalloc(img_size);
if (!buf) {
fclose(img_fp);
close(img_fd);
return -ENOMEM;
}
ret = read_fp(img_fp, buf, img_size);
ret = img_read(img_fd, buf, img_size);
close(img_fd);
if (ret) {
pr_perror("Unable to read from %s", img_path);
fclose(img_fp);
xfree(buf);
return ret;
}
fclose(img_fp);
e = criu_kfd__unpack(NULL, img_size, buf);
if (e == NULL) {
pr_err("Unable to parse the KFD message %#x\n", id);
@ -2266,25 +2258,23 @@ int init_dev(int dev_minor, amdgpu_device_handle *h_dev, uint64_t *max_copy_size
return 0;
}
FILE *get_bo_contents_fp(int id, int gpu_id, size_t tot_size)
static int get_bo_contents_fd(int id, int gpu_id, size_t tot_size)
{
char img_path[PATH_MAX];
size_t image_size = 0;
FILE *bo_contents_fp = NULL;
int fd;
snprintf(img_path, sizeof(img_path), IMG_KFD_PAGES_FILE, id, gpu_id);
bo_contents_fp = open_img_file(img_path, false, &image_size, true);
if (!bo_contents_fp) {
pr_perror("Cannot fopen %s", img_path);
return NULL;
}
fd = open_img_file(img_path, false, &image_size, true);
if (fd < 0)
return fd;
if (tot_size != image_size) {
pr_err("%s size mismatch (current:%ld:expected:%ld)\n", img_path, image_size, tot_size);
fclose(bo_contents_fp);
return NULL;
close(fd);
return -EINVAL;
}
return bo_contents_fp;
return fd;
}
struct parallel_thread_data {
@ -2301,7 +2291,7 @@ void *parallel_restore_bo_contents(void *_thread_data)
amdgpu_device_handle h_dev;
uint64_t max_copy_size;
size_t total_bo_size = 0, max_bo_size = 0, buffer_size = 0;
FILE *bo_contents_fp = NULL;
int bo_contents_fd = -1;
parallel_restore_entry *entry;
parallel_restore_cmd *restore_cmd = thread_data->restore_cmd;
off_t offset;
@ -2322,12 +2312,12 @@ void *parallel_restore_bo_contents(void *_thread_data)
buffer_size = kfd_max_buffer_size > 0 ? min(kfd_max_buffer_size, max_bo_size) : max_bo_size;
bo_contents_fp = get_bo_contents_fp(restore_cmd->cmd_head.id, thread_data->gpu_id, total_bo_size);
if (bo_contents_fp == NULL) {
ret = -1;
bo_contents_fd = get_bo_contents_fd(restore_cmd->cmd_head.id, thread_data->gpu_id, total_bo_size);
if (bo_contents_fd < 0) {
ret = bo_contents_fd;
goto err_sdma;
}
offset = ftello(bo_contents_fp);
offset = lseek(bo_contents_fd, 0, SEEK_CUR);
if (offset < 0) {
ret = -errno;
pr_perror("Failed to seek in parallel restore");
@ -2349,17 +2339,17 @@ void *parallel_restore_bo_contents(void *_thread_data)
continue;
entry = &restore_cmd->entries[i];
pos = fseeko(bo_contents_fp, entry->read_offset + offset,
SEEK_SET);
pos = lseek(bo_contents_fd, entry->read_offset + offset,
SEEK_SET);
if (pos < 0) {
ret = -errno;
pr_err("Failed to seek for BO using sDMA: bo_buckets[%d]\n", i);
goto err_sdma;
}
ret = sdma_copy_bo(restore_cmd->fds_write[entry->write_id], entry->size, bo_contents_fp,
buffer, buffer_size, h_dev,
max_copy_size, SDMA_OP_VRAM_WRITE, false);
ret = sdma_copy_bo(restore_cmd->fds_write[entry->write_id],
entry->size, bo_contents_fd, buffer,
buffer_size, h_dev, max_copy_size,
SDMA_OP_VRAM_WRITE, false);
if (ret) {
pr_err("Failed to fill the BO using sDMA: bo_buckets[%d]\n", i);
goto err_sdma;
@ -2367,8 +2357,8 @@ void *parallel_restore_bo_contents(void *_thread_data)
}
err_sdma:
if (bo_contents_fp)
fclose(bo_contents_fp);
if (bo_contents_fd >= 0)
close(bo_contents_fd);
if (buffer)
xfree(buffer);
amdgpu_device_deinitialize(h_dev);

View file

@ -96,39 +96,34 @@ int __amdgpu_plugin_dmabuf_dump(int dmabuf_fd, int id)
int amdgpu_plugin_dmabuf_restore(int id)
{
char path[PATH_MAX];
int fd_id, img_fd;
size_t img_size;
FILE *img_fp = NULL;
int ret = 0;
CriuDmabufNode *rd = NULL;
unsigned char *buf = NULL;
int fd_id;
snprintf(path, sizeof(path), IMG_DMABUF_FILE, id);
/* Read serialized metadata */
img_fp = open_img_file(path, false, &img_size, true);
if (!img_fp) {
img_fd = open_img_file(path, false, &img_size, true);
if (img_fd < 0) {
pr_err("Failed to open dmabuf metadata file: %s\n", path);
return -EINVAL;
return img_fd;
}
pr_debug("dmabuf Image file size:%ld\n", img_size);
buf = xmalloc(img_size);
if (!buf) {
pr_perror("Failed to allocate memory");
fclose(img_fp);
return -ENOMEM;
}
ret = read_fp(img_fp, buf, img_size);
fclose(img_fp);
ret = img_read(img_fd, buf, img_size);
close(img_fd);
if (ret) {
pr_perror("Unable to read from %s", path);
fclose(img_fp);
xfree(buf);
return ret;
}
fclose(img_fp);
rd = criu_dmabuf_node__unpack(NULL, img_size, buf);
if (rd == NULL) {

View file

@ -163,8 +163,8 @@ static int restore_bo_contents_drm(int drm_render_minor, CriuRenderNode *rd, int
amdgpu_device_handle h_dev;
uint64_t max_copy_size;
uint32_t major, minor;
FILE *bo_contents_fp = NULL;
void *buffer = NULL;
int bo_contents_fd;
char img_path[40];
int i, ret = 0;
@ -209,21 +209,20 @@ static int restore_bo_contents_drm(int drm_render_minor, CriuRenderNode *rd, int
snprintf(img_path, sizeof(img_path), IMG_DRM_PAGES_FILE, rd->id, drm_render_minor, i);
bo_contents_fp = open_img_file(img_path, false, &image_size, true);
if (!bo_contents_fp) {
ret = -errno;
bo_contents_fd = open_img_file(img_path, false, &image_size, true);
if (bo_contents_fd < 0) {
ret = bo_contents_fd;
break;
}
ret = sdma_copy_bo(dmabufs[i], rd->bo_entries[i]->size, bo_contents_fp, buffer, buffer_size, h_dev, max_copy_size,
SDMA_OP_VRAM_WRITE, true);
ret = sdma_copy_bo(dmabufs[i], rd->bo_entries[i]->size,
bo_contents_fd, buffer, buffer_size, h_dev,
max_copy_size, SDMA_OP_VRAM_WRITE, true);
close(bo_contents_fd);
if (ret) {
pr_err("Failed to fill the BO using sDMA: bo_buckets[%d]\n", i);
break;
}
if (bo_contents_fp)
fclose(bo_contents_fp);
}
exit:
@ -312,12 +311,12 @@ int amdgpu_plugin_drm_dump_file(int fd, int id, struct stat *drm)
DrmBoEntry *boinfo = rd->bo_entries[i];
struct drm_amdgpu_gem_list_handles_entry handle_entry = list_handles_entries[i];
union drm_amdgpu_gem_mmap mmap_args = { 0 };
int bo_contents_fd;
int dmabuf_fd;
uint32_t major, minor;
amdgpu_device_handle h_dev;
void *buffer = NULL;
char img_path[40];
FILE *bo_contents_fp = NULL;
int device_fd;
boinfo->size = handle_entry.size;
@ -407,9 +406,9 @@ int amdgpu_plugin_drm_dump_file(int fd, int id, struct stat *drm)
snprintf(img_path, sizeof(img_path), IMG_DRM_PAGES_FILE, rd->id, rd->drm_render_minor, i);
image_size = handle_entry.size;
bo_contents_fp = open_img_file(img_path, true, &image_size, true);
if (!bo_contents_fp) {
ret = -errno;
bo_contents_fd = open_img_file(img_path, true, &image_size, true);
if (bo_contents_fd < 0) {
ret = bo_contents_fd;
close(dmabuf_fd);
amdgpu_device_deinitialize(h_dev);
xfree(vm_info_entries);
@ -421,15 +420,17 @@ int amdgpu_plugin_drm_dump_file(int fd, int id, struct stat *drm)
errno = ret;
pr_perror("Failed to allocate buffer");
ret = -ret;
fclose(bo_contents_fp);
close(bo_contents_fd);
close(dmabuf_fd);
amdgpu_device_deinitialize(h_dev);
xfree(vm_info_entries);
goto exit;
}
ret = sdma_copy_bo(dmabuf_fd, handle_entry.size, bo_contents_fp, buffer, handle_entry.size, h_dev, 0x1000,
ret = sdma_copy_bo(dmabuf_fd, handle_entry.size, bo_contents_fd,
buffer, handle_entry.size, h_dev, 0x1000,
SDMA_OP_VRAM_READ, false);
close(bo_contents_fd);
if (ret)
goto exit;
@ -438,9 +439,6 @@ int amdgpu_plugin_drm_dump_file(int fd, int id, struct stat *drm)
if (dmabuf_fd != KFD_INVALID_FD)
close(dmabuf_fd);
if (bo_contents_fp)
fclose(bo_contents_fp);
ret = amdgpu_device_deinitialize(h_dev);
if (ret)
goto exit;

View file

@ -196,26 +196,52 @@ void clear_dumped_fds()
}
}
int read_fp(FILE *fp, void *buf, const size_t buf_len)
int img_read(int fd, void *buf, size_t buf_len)
{
size_t len_read;
char *ptr = buf;
len_read = fread(buf, 1, buf_len, fp);
if (len_read != buf_len) {
pr_err("Unable to read file (read:%ld buf_len:%ld)\n", len_read, buf_len);
return -EIO;
while (buf_len) {
ssize_t len = read(fd, ptr, buf_len);
if ((len < 0 && (errno != EINTR && errno != EAGAIN)) ||
(len == 0 && buf_len)) {
int ret;
ret = len ? -errno : -EIO;
errno = -ret;
pr_perror("Unable to read file (remain:%zu)", buf_len);
return ret;
}
if (len >= 0) {
buf_len -= len;
ptr += len;
}
}
return 0;
}
int write_fp(FILE *fp, const void *buf, const size_t buf_len)
int img_write(int fd, const void *buf, size_t buf_len)
{
size_t len_write;
const char *ptr = buf;
len_write = fwrite(buf, 1, buf_len, fp);
if (len_write != buf_len) {
pr_err("Unable to write file (wrote:%ld buf_len:%ld)\n", len_write, buf_len);
return -EIO;
while (buf_len) {
ssize_t len = write(fd, ptr, buf_len);
if ((len < 0 && (errno != EINTR && errno != EAGAIN)) ||
(len == 0 && buf_len)) {
int ret;
ret = len ? -errno : -EIO;
errno = -ret;
pr_perror("Unable to write file (remain:%zu)", buf_len);
return ret;
}
if (len >= 0) {
buf_len -= len;
ptr += len;
}
}
return 0;
}
@ -226,67 +252,65 @@ int write_fp(FILE *fp, const void *buf, const size_t buf_len)
* We store the size of the actual contents at the start of the file. (Note that
* the size of this field is architecture dependent!). This allows us to
* determine the file size when using criu_image_streamer when fseek and fstat
* are not available. The FILE * returned is already at the location of the
* first actual contents.
* are not available. The file descriptor returned is already at the location of
* the first actual contents.
*
* @param path The file path
* @param write False for read, true for write
* @param size Size of actual contents
* @param expect_present If true, the file not existing is an error
* @return FILE *if successful, NULL if failed
* @return file descriptor if successful, -errno on failure
*/
FILE *open_img_file(char *path, bool write, size_t *size, bool expect_present)
int open_img_file(char *path, bool write, size_t *size, bool expect_present)
{
FILE *fp = NULL;
int fd, ret;
if (opts.stream)
if (opts.stream) {
fd = img_streamer_open(path, write ? O_DUMP : O_RSTR);
else
fd = openat(criu_get_image_dir(), path, write ? (O_WRONLY | O_CREAT) : O_RDONLY, 0600);
if (fd < 0) {
if (expect_present)
pr_err("%s: Failed to open for %s\n", path, write ? "write" : "read");
return NULL;
if (fd == -1)
errno = EIO;
else if (fd < 0)
errno = -fd;
} else {
fd = openat(criu_get_image_dir(), path,
write ? (O_WRONLY | O_CREAT | O_TRUNC) : O_RDONLY,
0600);
}
fp = fdopen(fd, write ? "w" : "r");
if (!fp) {
pr_err("%s: Failed get pointer for %s\n", path, write ? "write" : "read");
close(fd);
return NULL;
if (fd < 0) {
fd = -errno;
if (expect_present)
pr_perror("%s: Failed to open for %s",
path, write ? "write" : "read");
return fd;
}
if (write)
ret = write_fp(fp, size, sizeof(*size));
ret = img_write(fd, size, sizeof(*size));
else
ret = read_fp(fp, size, sizeof(*size));
ret = img_read(fd, size, sizeof(*size));
if (ret) {
pr_err("%s:Failed to access file size\n", path);
fclose(fp);
errno = EIO;
return NULL;
close(fd);
return ret;
}
pr_debug("%s:Opened file for %s with size:%ld\n", path, write ? "write" : "read", *size);
return fp;
return fd;
}
int read_file(const char *file_path, void *buf, const size_t buf_len)
{
int ret;
FILE *fp;
int ret, fd;
fp = fopen(file_path, "r");
if (!fp) {
pr_err("Cannot fopen %s\n", file_path);
return -errno;
fd = open(file_path, O_RDONLY);
if (fd < 0) {
ret = -errno;
pr_perror("Cannot open %s", file_path);
return ret;
}
ret = read_fp(fp, buf, buf_len);
fclose(fp); /* this will also close fd */
ret = img_read(fd, buf, buf_len);
close(fd);
return ret;
}
@ -304,16 +328,15 @@ int read_file(const char *file_path, void *buf, const size_t buf_len)
*/
int write_img_file(char *path, const void *buf, const size_t buf_len)
{
int ret;
FILE *fp;
int ret, fd;
size_t len = buf_len;
fp = open_img_file(path, true, &len, true);
if (!fp)
return -errno;
fd = open_img_file(path, true, &len, true);
if (fd < 0)
return fd;
ret = write_fp(fp, buf, buf_len);
fclose(fp); /* this will also close fd */
ret = img_write(fd, buf, buf_len);
close(fd);
return ret;
}

View file

@ -106,11 +106,11 @@ extern bool kfd_vram_size_check;
extern bool kfd_numa_check;
extern bool kfd_capability_check;
int read_fp(FILE *fp, void *buf, const size_t buf_len);
int write_fp(FILE *fp, const void *buf, const size_t buf_len);
int img_read(int fd, void *buf, size_t buf_len);
int img_write(int fd, const void *buf, size_t buf_len);
int read_file(const char *file_path, void *buf, const size_t buf_len);
int write_img_file(char *path, const void *buf, const size_t buf_len);
FILE *open_img_file(char *path, bool write, size_t *size, bool expect_present);
int open_img_file(char *path, bool write, size_t *size, bool expect_present);
int record_dumped_fd(int fd, bool is_drm);
struct list_head *get_dumped_fds();
@ -127,7 +127,7 @@ void clear_restore_state();
void print_kfd_bo_stat(int bo_cnt, struct kfd_criu_bo_bucket *bo_list);
int sdma_copy_bo(int shared_fd, uint64_t size, FILE *storage_fp,
int sdma_copy_bo(int shared_fd, uint64_t size, int storage_fd,
void *buffer, size_t buffer_size, amdgpu_device_handle h_dev,
uint64_t max_copy_size, enum sdma_op_type type, bool do_not_free);