[CRIU] [PATCH 3/3] sysctl: move sysctl calls to usernsd

Tycho Andersen tycho.andersen at canonical.com
Tue Aug 18 08:44:09 PDT 2015


On Tue, Aug 18, 2015 at 06:23:05PM +0300, Pavel Emelyanov wrote:
> 
> > @@ -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.

alloca is just on the stack, so it doesn't need to be freed (although
I could move it to xmalloc() if you like).

> > +	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?

I tried this earlier, and it is a little ugly in terms of sending all
of the messages at once to usernsd.

Can we instead have usernsd install a service FD on the first such
request, and then close it when it shuts down?

Tycho


More information about the CRIU mailing list