[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