[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