static int pvcalls_back_bind()

in pvcalls-back.c [616:679]


static int pvcalls_back_bind(struct xenbus_device *dev,
			     struct xen_pvcalls_request *req)
{
	struct pvcalls_fedata *fedata;
	int ret;
	struct sockpass_mapping *map;
	struct xen_pvcalls_response *rsp;

	fedata = dev_get_drvdata(&dev->dev);

	map = kzalloc(sizeof(*map), GFP_KERNEL);
	if (map == NULL) {
		ret = -ENOMEM;
		goto out;
	}

	INIT_WORK(&map->register_work, __pvcalls_back_accept);
	spin_lock_init(&map->copy_lock);
	map->wq = alloc_workqueue("pvcalls_wq", WQ_UNBOUND, 1);
	if (!map->wq) {
		ret = -ENOMEM;
		goto out;
	}

	ret = sock_create(AF_INET, SOCK_STREAM, 0, &map->sock);
	if (ret < 0)
		goto out;

	ret = inet_bind(map->sock, (struct sockaddr *)&req->u.bind.addr,
			req->u.bind.len);
	if (ret < 0)
		goto out;

	map->fedata = fedata;
	map->id = req->u.bind.id;

	down(&fedata->socket_lock);
	ret = radix_tree_insert(&fedata->socketpass_mappings, map->id,
				map);
	up(&fedata->socket_lock);
	if (ret)
		goto out;

	write_lock_bh(&map->sock->sk->sk_callback_lock);
	map->saved_data_ready = map->sock->sk->sk_data_ready;
	map->sock->sk->sk_user_data = map;
	map->sock->sk->sk_data_ready = pvcalls_pass_sk_data_ready;
	write_unlock_bh(&map->sock->sk->sk_callback_lock);

out:
	if (ret) {
		if (map && map->sock)
			sock_release(map->sock);
		if (map && map->wq)
			destroy_workqueue(map->wq);
		kfree(map);
	}
	rsp = RING_GET_RESPONSE(&fedata->ring, fedata->ring.rsp_prod_pvt++);
	rsp->req_id = req->req_id;
	rsp->cmd = req->cmd;
	rsp->u.bind.id = req->u.bind.id;
	rsp->ret = ret;
	return 0;
}