[CRIU] [PATCH v2] cr-service: add lazy-pages RPC feature check

Andrei Vagin avagin at virtuozzo.com
Sun Mar 12 22:13:37 PDT 2017


On Wed, Mar 08, 2017 at 04:32:14PM +0100, Adrian Reber wrote:
> On Mon, Feb 27, 2017 at 10:21:04AM -0800, Andrei Vagin wrote:
> > On Thu, Feb 23, 2017 at 11:17:42AM +0100, Adrian Reber wrote:
> > > From: Adrian Reber <areber at redhat.com>
> > > 
> > > Extend the RPC feature check functionality to also test for lazy-pages
> > > support. This does not check for certain UFFD features (yet). Right now
> > > it only checks if kerndat_uffd() returns non-zero.
> > > 
> > > The RPC response is now transmitted from the forked process instead of
> > > encoding all the results into the return code. The parent RPC process
> > > now only sends an RPC message in the case of a failure.
> > > 
> > > Signed-off-by: Adrian Reber <areber at redhat.com>
> > > ---
> > >  criu/cr-service.c | 83 ++++++++++++++++++++++++++++++++++++++-----------------
> > >  images/rpc.proto  |  1 +
> > >  2 files changed, 59 insertions(+), 25 deletions(-)
> > > 
> > > diff --git a/criu/cr-service.c b/criu/cr-service.c
> > > index 169d637..d1007e7 100644
> > > --- a/criu/cr-service.c
> > > +++ b/criu/cr-service.c
> > > @@ -823,33 +823,21 @@ static int handle_feature_check(int sk, CriuReq * msg)
> > >  {
> > >  	CriuResp resp = CRIU_RESP__INIT;
> > >  	CriuFeatures feat = CRIU_FEATURES__INIT;
> > > -	bool success = false;
> > >  	int pid, status;
> > >  
> > >  	/* enable setting of an optional message */
> > >  	feat.has_mem_track = 1;
> > >  	feat.mem_track = false;
> > > +	feat.has_lazy_pages = 1;
> > > +	feat.lazy_pages = false;
> > >  
> > > -	/*
> > > -	 * Check if the requested feature check can be answered.
> > > -	 *
> > > -	 * This function is right now hard-coded to memory
> > > -	 * tracking detection and needs other/better logic to
> > > -	 * handle multiple feature checks.
> > > -	 */
> > > -	if (msg->features->has_mem_track != 1) {
> > > +	/* Check if the requested feature check can be answered. */
> > > +	if ((msg->features->has_mem_track != 1) ||
> > > +	    (msg->features->has_lazy_pages != 1)) {
> > >  		pr_warn("Feature checking for unknown feature.\n");
> > >  		goto out;
> > >  	}
> > >  
> > > -	/*
> > > -	 * From this point on the function will always
> > > -	 * 'succeed'. If the requested features are supported
> > > -	 * can be seen if the requested optional parameters are
> > > -	 * set in the message 'criu_features'.
> > > -	 */
> > > -	success = true;
> > > -
> > >  	pid = fork();
> > >  	if (pid < 0) {
> > >  		pr_perror("Can't fork");
> > > @@ -857,27 +845,72 @@ static int handle_feature_check(int sk, CriuReq * msg)
> > >  	}
> > >  
> > >  	if (pid == 0) {
> > > -		int ret = 1;
> > > +		int ret;
> > >  
> > >  		setproctitle("feature-check --rpc");
> > >  
> > > -		kerndat_get_dirty_track();
> > > +		if ((msg->features->has_mem_track == 1) &&
> > > +		    (msg->features->mem_track == true)) {
> > > +
> > > +			feat.mem_track = true;
> > > +			ret = kerndat_get_dirty_track();
> > > +
> > > +			if (ret)
> > > +				feat.mem_track = false;
> > > +
> > > +			if (!kdat.has_dirty_track)
> > > +				feat.mem_track = false;
> > > +		}
> > > +
> > > +		if ((msg->features->has_lazy_pages == 1) &&
> > > +		    (msg->features->lazy_pages == true)) {
> > > +			ret = kerndat_uffd(true);
> > 
> > offtopic: I like an idea when kerndat_* functions fill kdat and return
> > errors when they meet an unexpected error.
> 
> Yes, that is also what I thought working with it.
> 
> > 			if (kerndat_uffd())
> > 				goto err;
> > 
> > 			if (kdat.laze_pages)
> > 				feat.lazy_pages = true;
> > 
> > > +
> > > +			/*
> > > +			 * Not checking for specific UFFD features yet.
> > > +			 * If no error is returned it is probably
> > > +			 * enough for basic UFFD functionality. This can
> > > +			 * be extended in the future for a more detailed
> > > +			 * UFFD feature check.
> > > +			 */
> > > +			if (ret)
> > > +				feat.lazy_pages = false;
> > > +			else
> > > +				feat.lazy_pages = true;
> > > +		}
> > >  
> > > -		if (kdat.has_dirty_track)
> > > -			ret = 0;
> > > +		resp.features = &feat;
> > > +		resp.type = msg->type;
> > > +		/* The feature check is working, actual results are in resp.features */
> > > +		resp.success = true;
> > > +
> > > +		/*
> > > +		 * If this point is reached the information about the features
> > > +		 * is transmitted from the forked CRIU process (here).
> > > +		 * If an error occured earlier, the feature check response will be
> > > +		 * be send from the parent process.
> > > +		 */
> > > +		ret = send_criu_msg(sk, &resp);
> > >  
> > >  		exit(ret);
> > >  	}
> > >  
> > >  	wait(&status);
> > 
> > You don't check an exit code from wait here, so status may be
> > uninitialized. I recomend to use waitpid if pid is known.
> 
> Will send a new version of the patch. Pavel was easier as criu-dev
> maintainer ;-)

I'm sorry. I will try to be not so boring next time ;)

> 
> > > -	if (!WIFEXITED(status) || WEXITSTATUS(status))
> > > -		goto out;
> > > +	if (WIFEXITED(status) && !WEXITSTATUS(status))
> > > +		/*
> > > +		 * The child process exited was able to send the answer.
> > > +		 * Nothing more to do here.
> > > +		 */
> > > +		return 0;
> > >  
> > > -	feat.mem_track = true;
> > > +	/*
> > > +	 * The child process was not able to send an answer. Tell
> > > +	 * the RPC client that something did not work as expected.
> > > +	 */
> > >  out:
> > >  	resp.features = &feat;
> > 
> > I think we should not set feat here, should we?
> 
> Not sure. I removed it. Users should not read it anyway in an error
> case. But not setting it at all is probably the right thing to do.
> 
> > >  	resp.type = msg->type;
> > > -	resp.success = success;
> > > +	resp.success = false;
> > >  
> > >  	return send_criu_msg(sk, &resp);
> > >  }
> > > diff --git a/images/rpc.proto b/images/rpc.proto
> > > index f924b73..f894ae1 100644
> > > --- a/images/rpc.proto
> > > +++ b/images/rpc.proto
> > > @@ -148,6 +148,7 @@ enum criu_req_type {
> > >   */
> > >  message criu_features {
> > >  	optional bool			mem_track	= 1;
> > > +	optional bool			lazy_pages	= 2;
> > >  }
> > >  
> > >  /*
> > > -- 
> > > 2.9.3
> > > 
> 
> 		Adrian


More information about the CRIU mailing list