[CRIU] [PATCH 4/5] pipes: restore of pipe with O_DIRECT support
Stanislav Kinsburskiy
skinsbursky at virtuozzo.com
Tue Dec 15 02:58:03 PST 2015
Pipe with O_DIRECT can have many pipe entries in the hash.
Thus, instead of only one write, there must be a loop, performing all writes
sequentionally.
Signed-off-by: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>
---
pipes.c | 72 +++++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 42 insertions(+), 30 deletions(-)
diff --git a/pipes.c b/pipes.c
index cc13946..cdb12c6 100644
--- a/pipes.c
+++ b/pipes.c
@@ -166,29 +166,11 @@ void mark_pipe_master(void)
static struct pipe_data_rst *pd_hash_pipes[PIPE_DATA_HASH_SIZE];
-int restore_pipe_data(int img_type, int pfd, u32 id, struct pipe_data_rst **hash)
+static int restore_one_pipe_data(struct pipe_data_rst *pd, int pfd, u32 id)
{
int ret;
- struct pipe_data_rst *pd;
struct iovec iov;
- for (pd = hash[id & PIPE_DATA_HASH_MASK]; pd != NULL; pd = pd->next)
- if (pd->pde->pipe_id == id)
- break;
-
- if (!pd) { /* no data for this pipe */
- pr_info("No data for pipe %#x\n", id);
- return 0;
- }
-
- if (!pd->pde->bytes)
- goto out;
-
- if (!pd->data) {
- pr_err("Double data restore occurred on %#x\n", id);
- return -1;
- }
-
iov.iov_base = pd->data;
iov.iov_len = pd->pde->bytes;
@@ -196,14 +178,13 @@ int restore_pipe_data(int img_type, int pfd, u32 id, struct pipe_data_rst **hash
ret = vmsplice(pfd, &iov, 1, SPLICE_F_GIFT | SPLICE_F_NONBLOCK);
if (ret < 0) {
pr_perror("%#x: Error splicing data", id);
- goto err;
+ return -1;
}
if (ret == 0 || ret > iov.iov_len /* sanity */) {
pr_err("%#x: Wanted to restore %zu bytes, but got %d\n", id,
iov.iov_len, ret);
- ret = -1;
- goto err;
+ return -1;
}
iov.iov_base += ret;
@@ -222,18 +203,49 @@ int restore_pipe_data(int img_type, int pfd, u32 id, struct pipe_data_rst **hash
munmap(pd->data, pd->pde->bytes);
pd->data = NULL;
-out:
- ret = 0;
- if (pd->pde->has_size) {
+ return 0;
+}
+
+int restore_pipe_data(int img_type, int pfd, u32 id, struct pipe_data_rst **hash)
+{
+ int ret = 0;
+ struct pipe_data_rst *pd = NULL, *p;
+
+ for (p = hash[id & PIPE_DATA_HASH_MASK]; p != NULL; p = p->next) {
+ /* There can be more that one pipe_data_rst objects in case of
+ * pipes with O_DIRECT flag. Note, that all these objects has
+ * the same pd->pde->has_size and pd->pde->pipe_id.
+ * For ordinary pipes restore_one_pipe_data() will be called
+ * only once. */
+ if (p->pde->pipe_id != id)
+ continue;
+
+ pd = p;
+
+ if (!pd->pde->bytes)
+ continue;
+
+ if (!pd->data) {
+ pr_err("Double data restore occurred on %#x\n", id);
+ return -1;
+ }
+
+ ret = restore_one_pipe_data(pd, pfd, id);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (!pd) /* no data for this pipe */
+ pr_info("No data for pipe %#x\n", id);
+ else if (pd->pde->has_size) {
pr_info("Restoring size %#x for %#x\n",
pd->pde->size, pd->pde->pipe_id);
- ret = fcntl(pfd, F_SETPIPE_SZ, pd->pde->size);
- if (ret < 0)
+ if (fcntl(pfd, F_SETPIPE_SZ, pd->pde->size) < 0) {
pr_perror("Can't restore pipe size");
- else
- ret = 0;
+ ret = -1;
+ }
}
-err:
+
return ret;
}
More information about the CRIU
mailing list