[CRIU] [PATCH 12/12] unix: Add a method for choosing sender of packet in promiscous DGRAM queue
Andrew Vagin
avagin at virtuozzo.com
Mon May 16 12:46:35 PDT 2016
On Fri, Apr 29, 2016 at 05:37:48PM +0300, Kirill Tkhai wrote:
> Iterate over foreign sockets and find the right one to restore a packet.
> This allows to restore promiscous DGRAM queue with correct msg_names.
>
> Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
> ---
> criu/sk-unix.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 72 insertions(+)
>
> diff --git a/criu/sk-unix.c b/criu/sk-unix.c
> index 048d778..0ae0e61 100644
> --- a/criu/sk-unix.c
> +++ b/criu/sk-unix.c
> @@ -908,6 +908,75 @@ static int prep_unix_sk_cwd(struct unix_sk_info *ui, int *prev_cwd_fd)
> return 0;
> }
>
> +static int unix_get_fd(int *fds, int num, SkPacketEntry *pkt, struct sockaddr **addr,
> + socklen_t *addrlen, void *data)
> +{
> + struct unix_sk_info *send, *recv = (struct unix_sk_info *)data;
> + struct sockaddr_un *un;
> + int i, ret;
> +
> + *addr = xmalloc(sizeof(struct sockaddr_un));
> + if (!*addr)
> + return -1;
> + un = (struct sockaddr_un *)*addr;
> +
> + if (!pkt->has_sender_ino) {
> + ret = -1;
> + goto populate;
> + }
> +
> + send = find_unix_sk_by_ino(pkt->sender_ino);
> + if (!send) {
> + pr_err("Can't find socket with ino=%d\n", pkt->sender_ino);
> + goto free;
> + }
> + /*
> + * Since foreign fd is sent after it's bound,
> + * we don't have to wait send->prepared here.
> + */
> + for (i = 0; i < num; i++) {
> + *addrlen = sizeof(struct sockaddr_un);
> + ret = getsockname(fds[i], *addr, addrlen);
I think it should be optimized. getsockname() should not be called more
to restore each message.
> + if (ret < 0) {
> + pr_err("Can't get socket name\n");
> + goto free;
> + }
> + *addrlen -= sizeof(un->sun_family);
> +
> + if (*addrlen == send->ue->name.len &&
> + memcmp(un->sun_path, send->ue->name.data, *addrlen) == 0) {
> + ret = fds[i];
> +populate:
> + /* Reuse *addr to return receiver address */
> + *addrlen = recv->ue->name.len + sizeof(un->sun_family);
> + memcpy(un->sun_path, recv->ue->name.data, recv->ue->name.len);
> + un->sun_family = AF_UNIX;
> + return ret;
> + }
> + }
> +
> + pr_err("Do not owe socket with ino=%u\n", pkt->sender_ino);
> +free:
> + xfree(*addr);
> + *addr = NULL;
> + return -1;
> +}
> +
> +static int restore_promisc_queue(struct unix_sk_info *ui, int fd)
> +{
> + int *ffds = ui->foreign_fds, i;
> +
> + if (restore_sk_queue(ffds, ui->nr_senders, unix_get_fd, ui->ue->id, ui) < 0) {
> + pr_err("Can't restore rcv queue\n");
> + return -1;
> + }
> +
> + for (i = 0; i < ui->nr_senders; i++)
> + close(ffds[i]);
> +
> + return 0;
> +}
> +
> static int post_open_unix_sk(struct file_desc *d, int fd)
> {
> struct unix_sk_info *ui;
> @@ -919,6 +988,9 @@ static int post_open_unix_sk(struct file_desc *d, int fd)
> if (ui->flags & (USK_PAIR_MASTER | USK_PAIR_SLAVE))
> return 0;
>
> + if (ui->nr_senders && restore_promisc_queue(ui, fd))
> + return -1;
> +
> peer = ui->peer;
>
> if (peer == NULL)
>
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu
More information about the CRIU
mailing list