pvcalls-front.c (5842c83596fcfa742978ec2840440ab56c7fdf79) pvcalls-front.c (235a71c5390316429e2c7823119c5ea439816beb)
1/*
2 * (c) 2017 Stefano Stabellini <stefano@aporeto.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *

--- 185 unchanged lines hidden (view full) ---

194 wake_up(&bedata->inflight_req);
195 pvcalls_exit();
196 return IRQ_HANDLED;
197}
198
199static void pvcalls_front_free_map(struct pvcalls_bedata *bedata,
200 struct sock_mapping *map)
201{
1/*
2 * (c) 2017 Stefano Stabellini <stefano@aporeto.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *

--- 185 unchanged lines hidden (view full) ---

194 wake_up(&bedata->inflight_req);
195 pvcalls_exit();
196 return IRQ_HANDLED;
197}
198
199static void pvcalls_front_free_map(struct pvcalls_bedata *bedata,
200 struct sock_mapping *map)
201{
202 int i;
203
204 unbind_from_irqhandler(map->active.irq, map);
205
206 spin_lock(&bedata->socket_lock);
207 if (!list_empty(&map->list))
208 list_del_init(&map->list);
209 spin_unlock(&bedata->socket_lock);
210
211 for (i = 0; i < (1 << PVCALLS_RING_ORDER); i++)
212 gnttab_end_foreign_access(map->active.ring->ref[i], 0, 0);
213 gnttab_end_foreign_access(map->active.ref, 0, 0);
214 free_page((unsigned long)map->active.ring);
215
216 kfree(map);
202}
203
204static irqreturn_t pvcalls_front_conn_handler(int irq, void *sock_map)
205{
206 struct sock_mapping *map = sock_map;
207
208 if (map == NULL)
209 return IRQ_HANDLED;

--- 757 unchanged lines hidden (view full) ---

967 if (map->active_socket)
968 ret = pvcalls_front_poll_active(file, bedata, map, wait);
969 else
970 ret = pvcalls_front_poll_passive(file, bedata, map, wait);
971 pvcalls_exit();
972 return ret;
973}
974
217}
218
219static irqreturn_t pvcalls_front_conn_handler(int irq, void *sock_map)
220{
221 struct sock_mapping *map = sock_map;
222
223 if (map == NULL)
224 return IRQ_HANDLED;

--- 757 unchanged lines hidden (view full) ---

982 if (map->active_socket)
983 ret = pvcalls_front_poll_active(file, bedata, map, wait);
984 else
985 ret = pvcalls_front_poll_passive(file, bedata, map, wait);
986 pvcalls_exit();
987 return ret;
988}
989
990int pvcalls_front_release(struct socket *sock)
991{
992 struct pvcalls_bedata *bedata;
993 struct sock_mapping *map;
994 int req_id, notify, ret;
995 struct xen_pvcalls_request *req;
996
997 if (sock->sk == NULL)
998 return 0;
999
1000 pvcalls_enter();
1001 if (!pvcalls_front_dev) {
1002 pvcalls_exit();
1003 return -EIO;
1004 }
1005
1006 bedata = dev_get_drvdata(&pvcalls_front_dev->dev);
1007
1008 map = (struct sock_mapping *) sock->sk->sk_send_head;
1009 if (map == NULL) {
1010 pvcalls_exit();
1011 return 0;
1012 }
1013
1014 spin_lock(&bedata->socket_lock);
1015 ret = get_request(bedata, &req_id);
1016 if (ret < 0) {
1017 spin_unlock(&bedata->socket_lock);
1018 pvcalls_exit();
1019 return ret;
1020 }
1021 sock->sk->sk_send_head = NULL;
1022
1023 req = RING_GET_REQUEST(&bedata->ring, req_id);
1024 req->req_id = req_id;
1025 req->cmd = PVCALLS_RELEASE;
1026 req->u.release.id = (uintptr_t)map;
1027
1028 bedata->ring.req_prod_pvt++;
1029 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&bedata->ring, notify);
1030 spin_unlock(&bedata->socket_lock);
1031 if (notify)
1032 notify_remote_via_irq(bedata->irq);
1033
1034 wait_event(bedata->inflight_req,
1035 READ_ONCE(bedata->rsp[req_id].req_id) == req_id);
1036
1037 if (map->active_socket) {
1038 /*
1039 * Set in_error and wake up inflight_conn_req to force
1040 * recvmsg waiters to exit.
1041 */
1042 map->active.ring->in_error = -EBADF;
1043 wake_up_interruptible(&map->active.inflight_conn_req);
1044
1045 /*
1046 * Wait until there are no more waiters on the mutexes.
1047 * We know that no new waiters can be added because sk_send_head
1048 * is set to NULL -- we only need to wait for the existing
1049 * waiters to return.
1050 */
1051 while (!mutex_trylock(&map->active.in_mutex) ||
1052 !mutex_trylock(&map->active.out_mutex))
1053 cpu_relax();
1054
1055 pvcalls_front_free_map(bedata, map);
1056 } else {
1057 spin_lock(&bedata->socket_lock);
1058 list_del(&map->list);
1059 spin_unlock(&bedata->socket_lock);
1060 if (READ_ONCE(map->passive.inflight_req_id) !=
1061 PVCALLS_INVALID_ID) {
1062 pvcalls_front_free_map(bedata,
1063 map->passive.accept_map);
1064 }
1065 kfree(map);
1066 }
1067 WRITE_ONCE(bedata->rsp[req_id].req_id, PVCALLS_INVALID_ID);
1068
1069 pvcalls_exit();
1070 return 0;
1071}
1072
975static const struct xenbus_device_id pvcalls_front_ids[] = {
976 { "pvcalls" },
977 { "" }
978};
979
980static int pvcalls_front_remove(struct xenbus_device *dev)
981{
982 struct pvcalls_bedata *bedata;

--- 197 unchanged lines hidden ---
1073static const struct xenbus_device_id pvcalls_front_ids[] = {
1074 { "pvcalls" },
1075 { "" }
1076};
1077
1078static int pvcalls_front_remove(struct xenbus_device *dev)
1079{
1080 struct pvcalls_bedata *bedata;

--- 197 unchanged lines hidden ---