[CRIU] [PATCH 3/3] sysctl: move sysctl calls to usernsd
Pavel Emelyanov
xemul at parallels.com
Tue Aug 18 08:23:05 PDT 2015
> @@ -172,17 +218,44 @@ int sysctl_op(struct sysctl_req *req, size_t nr_req, int op)
> {
> int ret = 0;
> int dir = -1;
> + struct sysctl_userns_req *userns_req;
>
> - dir = open("/proc/sys", O_RDONLY);
> - if (dir < 0) {
> - pr_perror("Can't open sysctl dir");
> - return -1;
> - }
> + userns_req = alloca(MAX_MSG_SIZE);
I've found no place where this gets free()-ed.
> + userns_req->name = (char *) (&userns_req[1]);
>
> while (nr_req--) {
> - ret = __sysctl_op(dir, req, op);
> + int arg_len = sysctl_userns_arg_size(req->type);
> + int name_len = strlen(req->name) + 1;
> + int total_len = sizeof(*userns_req) + arg_len + name_len;
> +
> + if (total_len > MAX_MSG_SIZE) {
> + pr_err("sysctl msg too big: %s\n", req->name);
> + return -1;
> + }
> +
> + strcpy(userns_req->name, req->name);
> +
> + userns_req->arg = userns_req->name + name_len + 1;
> + if (op == CTL_WRITE)
> + memcpy(userns_req->arg, req->arg, arg_len);
> +
> + userns_req->type = req->type;
> + userns_req->flags = req->flags;
> + userns_req->op = op;
> +
> + ret = userns_call(__sysctl_op, UNS_ASYNC, userns_req, total_len, 0);
The __sysctl_op will open("/proc/sys" ...) on every request. This is not quite fast,
can we do all the sysctl_op-s it in one userns_call?
> if (ret < 0)
> break;
> +
> + /*
> + * Here, we use a little hack: since we only read in dump mode
> + * when usernsd is not active, we know the above call happened
> + * in this address space, so we can just copy the value read
> + * back out. If ther was an API to return stuff via
> + * userns_call(), that would be preferable.
> + */
> + if (op == CTL_READ)
> + memcpy(req->arg, userns_req->arg, arg_len);
> req++;
> }
>
>
More information about the CRIU
mailing list