[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