[CRIU] [PATCH] pb: Batch sigactions and rlimits writes

Pavel Emelyanov xemul at parallels.com
Mon Feb 3 12:18:42 PST 2014


perf shows we spend too much time writing 64 sigacts and
32 rlimits per task. Batch the writes.

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>

---

diff --git a/cr-dump.c b/cr-dump.c
index 2e5c542..4eb517a 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -321,26 +321,24 @@ static inline u_int64_t encode_rlim(unsigned long val)
 static int dump_task_rlims(int pid, struct cr_fdset *fds)
 {
 	int res, fd;
-
-	fd = fdset_fd(fds, CR_FD_RLIMIT);
+	RlimitEntry re[RLIM_NLIMITS];
 
 	for (res = 0; res < RLIM_NLIMITS; res++) {
 		struct rlimit lim;
-		RlimitEntry re = RLIMIT_ENTRY__INIT;
+
+		rlimit_entry__init(&re[res]);
 
 		if (prlimit(pid, res, NULL, &lim)) {
 			pr_perror("Can't get rlimit %d", res);
 			return -1;
 		}
 
-		re.cur = encode_rlim(lim.rlim_cur);
-		re.max = encode_rlim(lim.rlim_max);
-
-		if (pb_write_one(fd, &re, PB_RLIMIT))
-			return -1;
+		re[res].cur = encode_rlim(lim.rlim_cur);
+		re[res].max = encode_rlim(lim.rlim_max);
 	}
 
-	return 0;
+	fd = fdset_fd(fds, CR_FD_RLIMIT);
+	return pb_write_batch(fd, re, PB_RLIMIT, sizeof(RlimitEntry), res);
 }
 
 static int dump_filemap(pid_t pid, struct vma_area *vma_area,
diff --git a/include/protobuf.h b/include/protobuf.h
index ae9a65c..0c28e39 100644
--- a/include/protobuf.h
+++ b/include/protobuf.h
@@ -13,6 +13,7 @@ extern int do_pb_read_one(int fd, void **objp, int type, bool eof);
 #define pb_read_one_eof(fd, objp, type) do_pb_read_one(fd, (void **)objp, type, true)
 
 extern int pb_write_one(int fd, void *obj, int type);
+extern int pb_write_batch(int fd, void *obj, int type, unsigned osize, int nr);
 
 #define pb_pksize(__obj, __proto_message_name)						\
 	(__proto_message_name ##__get_packed_size(__obj) + sizeof(u32))
diff --git a/parasite-syscall.c b/parasite-syscall.c
index 2bc2ac0..8a998ed 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -575,8 +575,8 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id,
 int parasite_dump_sigacts_seized(struct parasite_ctl *ctl, struct cr_fdset *cr_fdset)
 {
 	struct parasite_dump_sa_args *args;
-	int ret, sig, fd;
-	SaEntry se = SA_ENTRY__INIT;
+	int ret, sig, fd, n = 0;
+	SaEntry se[SIGMAX - 2];
 
 	args = parasite_args(ctl, struct parasite_dump_sa_args);
 
@@ -584,24 +584,22 @@ int parasite_dump_sigacts_seized(struct parasite_ctl *ctl, struct cr_fdset *cr_f
 	if (ret < 0)
 		return ret;
 
-	fd = fdset_fd(cr_fdset, CR_FD_SIGACT);
-
 	for (sig = 1; sig <= SIGMAX; sig++) {
 		int i = sig - 1;
 
 		if (sig == SIGSTOP || sig == SIGKILL)
 			continue;
 
-		ASSIGN_TYPED(se.sigaction, encode_pointer(args->sas[i].rt_sa_handler));
-		ASSIGN_TYPED(se.flags, args->sas[i].rt_sa_flags);
-		ASSIGN_TYPED(se.restorer, encode_pointer(args->sas[i].rt_sa_restorer));
-		ASSIGN_TYPED(se.mask, args->sas[i].rt_sa_mask.sig[0]);
-
-		if (pb_write_one(fd, &se, PB_SIGACT) < 0)
-			return -1;
+		sa_entry__init(&se[n]);
+		ASSIGN_TYPED(se[n].sigaction, encode_pointer(args->sas[i].rt_sa_handler));
+		ASSIGN_TYPED(se[n].flags, args->sas[i].rt_sa_flags);
+		ASSIGN_TYPED(se[n].restorer, encode_pointer(args->sas[i].rt_sa_restorer));
+		ASSIGN_TYPED(se[n].mask, args->sas[i].rt_sa_mask.sig[0]);
+		n++;
 	}
 
-	return 0;
+	fd = fdset_fd(cr_fdset, CR_FD_SIGACT);
+	return pb_write_batch(fd, se, PB_SIGACT, sizeof(SaEntry), n);
 }
 
 static int dump_one_timer(struct itimerval *v, int fd)
diff --git a/protobuf.c b/protobuf.c
index 6bf3da9..42fe633 100644
--- a/protobuf.c
+++ b/protobuf.c
@@ -601,6 +601,8 @@ int pb_write_one(int fd, void *obj, int type)
 	int ret = -1;
 	struct iovec iov[2];
 
+	pr_info("WRX %d\n", type);
+
 	if (!cr_pb_descs[type].pb_desc) {
 		pr_err("Wrong object requested %d\n", type);
 		return -1;
@@ -637,6 +639,54 @@ err:
 	return ret;
 }
 
+int pb_write_batch(int fd, void *obj, int type, unsigned osize, int nr)
+{
+	u32 size, packed, total = 0;
+	int ret = -1, i;
+	struct iovec iov[nr];
+
+	pr_info("WRX %d\n", type);
+
+	if (!cr_pb_descs[type].pb_desc) {
+		pr_err("Wrong object requested %d\n", type);
+		return -1;
+	}
+
+	for (i = 0; i < nr; i++) {
+		unsigned int blen;
+		void *buf;
+
+		size = cr_pb_descs[type].getpksize(obj);
+		blen = size + sizeof(size);
+		buf = xmalloc(blen);
+		if (!buf)
+			goto err;
+
+		packed = cr_pb_descs[type].pack(obj, buf + sizeof(size));
+		if (packed != size) {
+			pr_err("Failed packing PB object %p\n", obj);
+			goto err;
+		}
+
+		*(u32*)buf = size;
+		iov[i].iov_base = buf;
+		iov[i].iov_len = blen;
+		total += blen;
+		obj += osize;
+	}
+
+	ret = writev(fd, iov, nr);
+	if (ret != total) {
+		pr_perror("Can't write %d bytes", (int)total);
+		goto err;
+	}
+
+	ret = 0;
+err:
+	while (i--)
+		xfree(iov[i].iov_base);
+	return ret;
+}
 int collect_image(struct collect_image_info *cinfo)
 {
 	int fd, ret;


More information about the CRIU mailing list