[CRIU] [PATCH RFC 21/30] unix: Wait a peer using task_st futex

Kirill Tkhai ktkhai at virtuozzo.com
Tue Nov 29 03:04:44 PST 2016



On 08.11.2016 16:07, Pavel Emelyanov wrote:
> On 11/01/2016 05:33 PM, Kirill Tkhai wrote:
>> Use new task_st futex notifier instead of per-socket.
> 
> I don't get this change. Why can't we wait on per-socket lock
> and should wait on per-task one?

The idea is to use task_st futex for waiting of every events.
This allows to sleep on it. Impossible to sleep on a bunch of
futexes of different event types at once.
 
>> The step to make open file non-blocking but task_st.
>>
>> Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
>> ---
>>  criu/sk-unix.c |   38 +++++++++++++++++++++++++++-----------
>>  1 file changed, 27 insertions(+), 11 deletions(-)
>>
>> diff --git a/criu/sk-unix.c b/criu/sk-unix.c
>> index a3301fc..49720da 100644
>> --- a/criu/sk-unix.c
>> +++ b/criu/sk-unix.c
>> @@ -785,13 +785,6 @@ struct unix_sk_info {
>>  	struct list_head node; /* To link in peer's connected list  */
>>  
>>  	/*
>> -	 * Futex to signal when the socket is prepared. In particular, we
>> -	 * signal after bind()ing the socket if it is not in TCP_LISTEN, or
>> -	 * after listen() if the socket is in TCP_LISTEN.
>> -	 */
>> -	futex_t prepared;
>> -
>> -	/*
>>  	 * For DGRAM sockets with queues, we should only restore the queue
>>  	 * once although it may be open by more than one tid. This is the peer
>>  	 * that should do the queueing.
>> @@ -814,6 +807,29 @@ static struct unix_sk_info *find_unix_sk_by_ino(int ino)
>>  	return NULL;
>>  }
>>  
>> +static int wake_connected_sockets(struct unix_sk_info *ui)
>> +{
>> +	struct fdinfo_list_entry *fle;
>> +	struct unix_sk_info *tmp;
>> +
>> +	list_for_each_entry(tmp, &ui->connected, node) {
>> +		fle = file_master(&tmp->d);
>> +		set_fds_event(fle->pid);
>> +	}
>> +	return 0;
>> +}
>> +
>> +static bool peer_is_not_prepared(struct unix_sk_info *peer)
>> +{
>> +	struct fdinfo_list_entry *fle;
>> +	fle = file_master(&peer->d);
>> +
>> +	if (peer->ue->state != TCP_LISTEN)
>> +		return (fle->stage < FLE_BOUND) ? true : false;
>> +	else
>> +		return (fle->stage < FLE_LISTEN) ? true : false;
>> +}
>> +
>>  static int shutdown_unix_sk(int sk, struct unix_sk_info *ui)
>>  {
>>  	int how;
>> @@ -886,7 +902,8 @@ static int post_open_unix_sk(struct file_desc *d, int fd)
>>  
>>  	/* Skip external sockets */
>>  	if (!list_empty(&peer->d.fd_info_head))
>> -		futex_wait_while(&peer->prepared, 0);
>> +		while (peer_is_not_prepared(peer))
>> +			wait_fds_event();
>>  
>>  	if (ui->ue->uflags & USK_INHERIT)
>>  		return 0;
>> @@ -1028,9 +1045,9 @@ static int bind_unix_sk(int sk, struct unix_sk_info *ui)
>>  	}
>>  
>>  	if (ui->ue->state != TCP_LISTEN) {
>> -		futex_set_and_wake(&ui->prepared, 1);
>>  		fle = file_master(&ui->d);
>>  		fle->stage = FLE_BOUND;
>> +		wake_connected_sockets(ui);
>>  	}
>>  
>>  	ret = 0;
>> @@ -1240,9 +1257,9 @@ static int open_unixsk_standalone(struct unix_sk_info *ui)
>>  			pr_perror("Can't make usk listen");
>>  			return -1;
>>  		}
>> -		futex_set_and_wake(&ui->prepared, 1);
>>  		fle = file_master(&ui->d);
>>  		fle->stage = FLE_LISTEN;
>> +		wake_connected_sockets(ui);
>>  	}
>>  out:
>>  	if (rst_file_params(sk, ui->ue->fown, ui->ue->flags))
>> @@ -1347,7 +1364,6 @@ static int collect_one_unixsk(void *o, ProtobufCMessage *base, struct cr_img *i)
>>  	} else
>>  		ui->name = NULL;
>>  
>> -	futex_init(&ui->prepared);
>>  	ui->queuer = 0;
>>  	ui->peer = NULL;
>>  	INIT_LIST_HEAD(&ui->connected);
>>
>> .
>>
> 


More information about the CRIU mailing list