18c3e34a4SDavid Howells /* RxRPC individual remote procedure call handling 28c3e34a4SDavid Howells * 38c3e34a4SDavid Howells * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 48c3e34a4SDavid Howells * Written by David Howells (dhowells@redhat.com) 58c3e34a4SDavid Howells * 68c3e34a4SDavid Howells * This program is free software; you can redistribute it and/or 78c3e34a4SDavid Howells * modify it under the terms of the GNU General Public License 88c3e34a4SDavid Howells * as published by the Free Software Foundation; either version 98c3e34a4SDavid Howells * 2 of the License, or (at your option) any later version. 108c3e34a4SDavid Howells */ 118c3e34a4SDavid Howells 128c3e34a4SDavid Howells #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 138c3e34a4SDavid Howells 148c3e34a4SDavid Howells #include <linux/slab.h> 158c3e34a4SDavid Howells #include <linux/module.h> 168c3e34a4SDavid Howells #include <linux/circ_buf.h> 178c3e34a4SDavid Howells #include <linux/hashtable.h> 188c3e34a4SDavid Howells #include <linux/spinlock_types.h> 198c3e34a4SDavid Howells #include <net/sock.h> 208c3e34a4SDavid Howells #include <net/af_rxrpc.h> 218c3e34a4SDavid Howells #include "ar-internal.h" 228c3e34a4SDavid Howells 238c3e34a4SDavid Howells /* 248c3e34a4SDavid Howells * Maximum lifetime of a call (in jiffies). 258c3e34a4SDavid Howells */ 268c3e34a4SDavid Howells unsigned int rxrpc_max_call_lifetime = 60 * HZ; 278c3e34a4SDavid Howells 288c3e34a4SDavid Howells /* 298c3e34a4SDavid Howells * Time till dead call expires after last use (in jiffies). 308c3e34a4SDavid Howells */ 318c3e34a4SDavid Howells unsigned int rxrpc_dead_call_expiry = 2 * HZ; 328c3e34a4SDavid Howells 338c3e34a4SDavid Howells const char *const rxrpc_call_states[NR__RXRPC_CALL_STATES] = { 348c3e34a4SDavid Howells [RXRPC_CALL_CLIENT_SEND_REQUEST] = "ClSndReq", 358c3e34a4SDavid Howells [RXRPC_CALL_CLIENT_AWAIT_REPLY] = "ClAwtRpl", 368c3e34a4SDavid Howells [RXRPC_CALL_CLIENT_RECV_REPLY] = "ClRcvRpl", 378c3e34a4SDavid Howells [RXRPC_CALL_CLIENT_FINAL_ACK] = "ClFnlACK", 388c3e34a4SDavid Howells [RXRPC_CALL_SERVER_SECURING] = "SvSecure", 398c3e34a4SDavid Howells [RXRPC_CALL_SERVER_ACCEPTING] = "SvAccept", 408c3e34a4SDavid Howells [RXRPC_CALL_SERVER_RECV_REQUEST] = "SvRcvReq", 418c3e34a4SDavid Howells [RXRPC_CALL_SERVER_ACK_REQUEST] = "SvAckReq", 428c3e34a4SDavid Howells [RXRPC_CALL_SERVER_SEND_REPLY] = "SvSndRpl", 438c3e34a4SDavid Howells [RXRPC_CALL_SERVER_AWAIT_ACK] = "SvAwtACK", 448c3e34a4SDavid Howells [RXRPC_CALL_COMPLETE] = "Complete", 458c3e34a4SDavid Howells [RXRPC_CALL_SERVER_BUSY] = "SvBusy ", 468c3e34a4SDavid Howells [RXRPC_CALL_REMOTELY_ABORTED] = "RmtAbort", 478c3e34a4SDavid Howells [RXRPC_CALL_LOCALLY_ABORTED] = "LocAbort", 488c3e34a4SDavid Howells [RXRPC_CALL_NETWORK_ERROR] = "NetError", 498c3e34a4SDavid Howells [RXRPC_CALL_DEAD] = "Dead ", 508c3e34a4SDavid Howells }; 518c3e34a4SDavid Howells 528c3e34a4SDavid Howells struct kmem_cache *rxrpc_call_jar; 538c3e34a4SDavid Howells LIST_HEAD(rxrpc_calls); 548c3e34a4SDavid Howells DEFINE_RWLOCK(rxrpc_call_lock); 558c3e34a4SDavid Howells 568c3e34a4SDavid Howells static void rxrpc_destroy_call(struct work_struct *work); 578c3e34a4SDavid Howells static void rxrpc_call_life_expired(unsigned long _call); 588c3e34a4SDavid Howells static void rxrpc_dead_call_expired(unsigned long _call); 598c3e34a4SDavid Howells static void rxrpc_ack_time_expired(unsigned long _call); 608c3e34a4SDavid Howells static void rxrpc_resend_time_expired(unsigned long _call); 618c3e34a4SDavid Howells 628c3e34a4SDavid Howells static DEFINE_SPINLOCK(rxrpc_call_hash_lock); 638c3e34a4SDavid Howells static DEFINE_HASHTABLE(rxrpc_call_hash, 10); 648c3e34a4SDavid Howells 658c3e34a4SDavid Howells /* 668c3e34a4SDavid Howells * Hash function for rxrpc_call_hash 678c3e34a4SDavid Howells */ 688c3e34a4SDavid Howells static unsigned long rxrpc_call_hashfunc( 698c3e34a4SDavid Howells u8 in_clientflag, 708c3e34a4SDavid Howells u32 cid, 718c3e34a4SDavid Howells u32 call_id, 728c3e34a4SDavid Howells u32 epoch, 738c3e34a4SDavid Howells u16 service_id, 7419ffa01cSDavid Howells sa_family_t family, 758c3e34a4SDavid Howells void *localptr, 768c3e34a4SDavid Howells unsigned int addr_size, 778c3e34a4SDavid Howells const u8 *peer_addr) 788c3e34a4SDavid Howells { 798c3e34a4SDavid Howells const u16 *p; 808c3e34a4SDavid Howells unsigned int i; 818c3e34a4SDavid Howells unsigned long key; 828c3e34a4SDavid Howells 838c3e34a4SDavid Howells _enter(""); 848c3e34a4SDavid Howells 858c3e34a4SDavid Howells key = (unsigned long)localptr; 868c3e34a4SDavid Howells /* We just want to add up the __be32 values, so forcing the 878c3e34a4SDavid Howells * cast should be okay. 888c3e34a4SDavid Howells */ 898c3e34a4SDavid Howells key += epoch; 908c3e34a4SDavid Howells key += service_id; 918c3e34a4SDavid Howells key += call_id; 928c3e34a4SDavid Howells key += (cid & RXRPC_CIDMASK) >> RXRPC_CIDSHIFT; 938c3e34a4SDavid Howells key += cid & RXRPC_CHANNELMASK; 948c3e34a4SDavid Howells key += in_clientflag; 9519ffa01cSDavid Howells key += family; 968c3e34a4SDavid Howells /* Step through the peer address in 16-bit portions for speed */ 978c3e34a4SDavid Howells for (i = 0, p = (const u16 *)peer_addr; i < addr_size >> 1; i++, p++) 988c3e34a4SDavid Howells key += *p; 998c3e34a4SDavid Howells _leave(" key = 0x%lx", key); 1008c3e34a4SDavid Howells return key; 1018c3e34a4SDavid Howells } 1028c3e34a4SDavid Howells 1038c3e34a4SDavid Howells /* 1048c3e34a4SDavid Howells * Add a call to the hashtable 1058c3e34a4SDavid Howells */ 1068c3e34a4SDavid Howells static void rxrpc_call_hash_add(struct rxrpc_call *call) 1078c3e34a4SDavid Howells { 1088c3e34a4SDavid Howells unsigned long key; 1098c3e34a4SDavid Howells unsigned int addr_size = 0; 1108c3e34a4SDavid Howells 1118c3e34a4SDavid Howells _enter(""); 11219ffa01cSDavid Howells switch (call->family) { 1138c3e34a4SDavid Howells case AF_INET: 1148c3e34a4SDavid Howells addr_size = sizeof(call->peer_ip.ipv4_addr); 1158c3e34a4SDavid Howells break; 1168c3e34a4SDavid Howells case AF_INET6: 1178c3e34a4SDavid Howells addr_size = sizeof(call->peer_ip.ipv6_addr); 1188c3e34a4SDavid Howells break; 1198c3e34a4SDavid Howells default: 1208c3e34a4SDavid Howells break; 1218c3e34a4SDavid Howells } 1228c3e34a4SDavid Howells key = rxrpc_call_hashfunc(call->in_clientflag, call->cid, 1238c3e34a4SDavid Howells call->call_id, call->epoch, 12419ffa01cSDavid Howells call->service_id, call->family, 1258c3e34a4SDavid Howells call->conn->trans->local, addr_size, 1268c3e34a4SDavid Howells call->peer_ip.ipv6_addr); 1278c3e34a4SDavid Howells /* Store the full key in the call */ 1288c3e34a4SDavid Howells call->hash_key = key; 1298c3e34a4SDavid Howells spin_lock(&rxrpc_call_hash_lock); 1308c3e34a4SDavid Howells hash_add_rcu(rxrpc_call_hash, &call->hash_node, key); 1318c3e34a4SDavid Howells spin_unlock(&rxrpc_call_hash_lock); 1328c3e34a4SDavid Howells _leave(""); 1338c3e34a4SDavid Howells } 1348c3e34a4SDavid Howells 1358c3e34a4SDavid Howells /* 1368c3e34a4SDavid Howells * Remove a call from the hashtable 1378c3e34a4SDavid Howells */ 1388c3e34a4SDavid Howells static void rxrpc_call_hash_del(struct rxrpc_call *call) 1398c3e34a4SDavid Howells { 1408c3e34a4SDavid Howells _enter(""); 1418c3e34a4SDavid Howells spin_lock(&rxrpc_call_hash_lock); 1428c3e34a4SDavid Howells hash_del_rcu(&call->hash_node); 1438c3e34a4SDavid Howells spin_unlock(&rxrpc_call_hash_lock); 1448c3e34a4SDavid Howells _leave(""); 1458c3e34a4SDavid Howells } 1468c3e34a4SDavid Howells 1478c3e34a4SDavid Howells /* 1488c3e34a4SDavid Howells * Find a call in the hashtable and return it, or NULL if it 1498c3e34a4SDavid Howells * isn't there. 1508c3e34a4SDavid Howells */ 1518c3e34a4SDavid Howells struct rxrpc_call *rxrpc_find_call_hash( 1528c3e34a4SDavid Howells struct rxrpc_host_header *hdr, 1538c3e34a4SDavid Howells void *localptr, 15419ffa01cSDavid Howells sa_family_t family, 1558c3e34a4SDavid Howells const void *peer_addr) 1568c3e34a4SDavid Howells { 1578c3e34a4SDavid Howells unsigned long key; 1588c3e34a4SDavid Howells unsigned int addr_size = 0; 1598c3e34a4SDavid Howells struct rxrpc_call *call = NULL; 1608c3e34a4SDavid Howells struct rxrpc_call *ret = NULL; 1618c3e34a4SDavid Howells u8 in_clientflag = hdr->flags & RXRPC_CLIENT_INITIATED; 1628c3e34a4SDavid Howells 1638c3e34a4SDavid Howells _enter(""); 16419ffa01cSDavid Howells switch (family) { 1658c3e34a4SDavid Howells case AF_INET: 1668c3e34a4SDavid Howells addr_size = sizeof(call->peer_ip.ipv4_addr); 1678c3e34a4SDavid Howells break; 1688c3e34a4SDavid Howells case AF_INET6: 1698c3e34a4SDavid Howells addr_size = sizeof(call->peer_ip.ipv6_addr); 1708c3e34a4SDavid Howells break; 1718c3e34a4SDavid Howells default: 1728c3e34a4SDavid Howells break; 1738c3e34a4SDavid Howells } 1748c3e34a4SDavid Howells 1758c3e34a4SDavid Howells key = rxrpc_call_hashfunc(in_clientflag, hdr->cid, hdr->callNumber, 1768c3e34a4SDavid Howells hdr->epoch, hdr->serviceId, 17719ffa01cSDavid Howells family, localptr, addr_size, 1788c3e34a4SDavid Howells peer_addr); 1798c3e34a4SDavid Howells hash_for_each_possible_rcu(rxrpc_call_hash, call, hash_node, key) { 1808c3e34a4SDavid Howells if (call->hash_key == key && 1818c3e34a4SDavid Howells call->call_id == hdr->callNumber && 1828c3e34a4SDavid Howells call->cid == hdr->cid && 1838c3e34a4SDavid Howells call->in_clientflag == in_clientflag && 1848c3e34a4SDavid Howells call->service_id == hdr->serviceId && 18519ffa01cSDavid Howells call->family == family && 1868c3e34a4SDavid Howells call->local == localptr && 1878c3e34a4SDavid Howells memcmp(call->peer_ip.ipv6_addr, peer_addr, 1888c3e34a4SDavid Howells addr_size) == 0 && 1898c3e34a4SDavid Howells call->epoch == hdr->epoch) { 1908c3e34a4SDavid Howells ret = call; 1918c3e34a4SDavid Howells break; 1928c3e34a4SDavid Howells } 1938c3e34a4SDavid Howells } 1948c3e34a4SDavid Howells _leave(" = %p", ret); 1958c3e34a4SDavid Howells return ret; 1968c3e34a4SDavid Howells } 1978c3e34a4SDavid Howells 1988c3e34a4SDavid Howells /* 1998c3e34a4SDavid Howells * find an extant server call 2008c3e34a4SDavid Howells * - called in process context with IRQs enabled 2018c3e34a4SDavid Howells */ 2028c3e34a4SDavid Howells struct rxrpc_call *rxrpc_find_call_by_user_ID(struct rxrpc_sock *rx, 2038c3e34a4SDavid Howells unsigned long user_call_ID) 2048c3e34a4SDavid Howells { 2058c3e34a4SDavid Howells struct rxrpc_call *call; 2068c3e34a4SDavid Howells struct rb_node *p; 2078c3e34a4SDavid Howells 2088c3e34a4SDavid Howells _enter("%p,%lx", rx, user_call_ID); 2098c3e34a4SDavid Howells 2108c3e34a4SDavid Howells read_lock(&rx->call_lock); 2118c3e34a4SDavid Howells 2128c3e34a4SDavid Howells p = rx->calls.rb_node; 2138c3e34a4SDavid Howells while (p) { 2148c3e34a4SDavid Howells call = rb_entry(p, struct rxrpc_call, sock_node); 2158c3e34a4SDavid Howells 2168c3e34a4SDavid Howells if (user_call_ID < call->user_call_ID) 2178c3e34a4SDavid Howells p = p->rb_left; 2188c3e34a4SDavid Howells else if (user_call_ID > call->user_call_ID) 2198c3e34a4SDavid Howells p = p->rb_right; 2208c3e34a4SDavid Howells else 2218c3e34a4SDavid Howells goto found_extant_call; 2228c3e34a4SDavid Howells } 2238c3e34a4SDavid Howells 2248c3e34a4SDavid Howells read_unlock(&rx->call_lock); 2258c3e34a4SDavid Howells _leave(" = NULL"); 2268c3e34a4SDavid Howells return NULL; 2278c3e34a4SDavid Howells 2288c3e34a4SDavid Howells found_extant_call: 2298c3e34a4SDavid Howells rxrpc_get_call(call); 2308c3e34a4SDavid Howells read_unlock(&rx->call_lock); 2318c3e34a4SDavid Howells _leave(" = %p [%d]", call, atomic_read(&call->usage)); 2328c3e34a4SDavid Howells return call; 2338c3e34a4SDavid Howells } 2348c3e34a4SDavid Howells 2358c3e34a4SDavid Howells /* 2368c3e34a4SDavid Howells * allocate a new call 2378c3e34a4SDavid Howells */ 2388c3e34a4SDavid Howells static struct rxrpc_call *rxrpc_alloc_call(gfp_t gfp) 2398c3e34a4SDavid Howells { 2408c3e34a4SDavid Howells struct rxrpc_call *call; 2418c3e34a4SDavid Howells 2428c3e34a4SDavid Howells call = kmem_cache_zalloc(rxrpc_call_jar, gfp); 2438c3e34a4SDavid Howells if (!call) 2448c3e34a4SDavid Howells return NULL; 2458c3e34a4SDavid Howells 2468c3e34a4SDavid Howells call->acks_winsz = 16; 2478c3e34a4SDavid Howells call->acks_window = kmalloc(call->acks_winsz * sizeof(unsigned long), 2488c3e34a4SDavid Howells gfp); 2498c3e34a4SDavid Howells if (!call->acks_window) { 2508c3e34a4SDavid Howells kmem_cache_free(rxrpc_call_jar, call); 2518c3e34a4SDavid Howells return NULL; 2528c3e34a4SDavid Howells } 2538c3e34a4SDavid Howells 2548c3e34a4SDavid Howells setup_timer(&call->lifetimer, &rxrpc_call_life_expired, 2558c3e34a4SDavid Howells (unsigned long) call); 2568c3e34a4SDavid Howells setup_timer(&call->deadspan, &rxrpc_dead_call_expired, 2578c3e34a4SDavid Howells (unsigned long) call); 2588c3e34a4SDavid Howells setup_timer(&call->ack_timer, &rxrpc_ack_time_expired, 2598c3e34a4SDavid Howells (unsigned long) call); 2608c3e34a4SDavid Howells setup_timer(&call->resend_timer, &rxrpc_resend_time_expired, 2618c3e34a4SDavid Howells (unsigned long) call); 2628c3e34a4SDavid Howells INIT_WORK(&call->destroyer, &rxrpc_destroy_call); 2638c3e34a4SDavid Howells INIT_WORK(&call->processor, &rxrpc_process_call); 2648c3e34a4SDavid Howells INIT_LIST_HEAD(&call->accept_link); 2658c3e34a4SDavid Howells skb_queue_head_init(&call->rx_queue); 2668c3e34a4SDavid Howells skb_queue_head_init(&call->rx_oos_queue); 2678c3e34a4SDavid Howells init_waitqueue_head(&call->tx_waitq); 2688c3e34a4SDavid Howells spin_lock_init(&call->lock); 2698c3e34a4SDavid Howells rwlock_init(&call->state_lock); 2708c3e34a4SDavid Howells atomic_set(&call->usage, 1); 2718c3e34a4SDavid Howells call->debug_id = atomic_inc_return(&rxrpc_debug_id); 2728c3e34a4SDavid Howells call->state = RXRPC_CALL_CLIENT_SEND_REQUEST; 2738c3e34a4SDavid Howells 2748c3e34a4SDavid Howells memset(&call->sock_node, 0xed, sizeof(call->sock_node)); 2758c3e34a4SDavid Howells 2768c3e34a4SDavid Howells call->rx_data_expect = 1; 2778c3e34a4SDavid Howells call->rx_data_eaten = 0; 2788c3e34a4SDavid Howells call->rx_first_oos = 0; 2798c3e34a4SDavid Howells call->ackr_win_top = call->rx_data_eaten + 1 + rxrpc_rx_window_size; 2808c3e34a4SDavid Howells call->creation_jif = jiffies; 2818c3e34a4SDavid Howells return call; 2828c3e34a4SDavid Howells } 2838c3e34a4SDavid Howells 2848c3e34a4SDavid Howells /* 2858c3e34a4SDavid Howells * allocate a new client call and attempt to get a connection slot for it 2868c3e34a4SDavid Howells */ 2878c3e34a4SDavid Howells static struct rxrpc_call *rxrpc_alloc_client_call( 2888c3e34a4SDavid Howells struct rxrpc_sock *rx, 28919ffa01cSDavid Howells struct rxrpc_conn_parameters *cp, 2908c3e34a4SDavid Howells struct rxrpc_transport *trans, 2918c3e34a4SDavid Howells struct rxrpc_conn_bundle *bundle, 2928c3e34a4SDavid Howells gfp_t gfp) 2938c3e34a4SDavid Howells { 2948c3e34a4SDavid Howells struct rxrpc_call *call; 2958c3e34a4SDavid Howells int ret; 2968c3e34a4SDavid Howells 2978c3e34a4SDavid Howells _enter(""); 2988c3e34a4SDavid Howells 2998c3e34a4SDavid Howells ASSERT(rx != NULL); 3008c3e34a4SDavid Howells ASSERT(trans != NULL); 3018c3e34a4SDavid Howells ASSERT(bundle != NULL); 3028c3e34a4SDavid Howells 3038c3e34a4SDavid Howells call = rxrpc_alloc_call(gfp); 3048c3e34a4SDavid Howells if (!call) 3058c3e34a4SDavid Howells return ERR_PTR(-ENOMEM); 3068c3e34a4SDavid Howells 3078c3e34a4SDavid Howells sock_hold(&rx->sk); 3088c3e34a4SDavid Howells call->socket = rx; 3098c3e34a4SDavid Howells call->rx_data_post = 1; 3108c3e34a4SDavid Howells 31119ffa01cSDavid Howells ret = rxrpc_connect_call(rx, cp, trans, bundle, call, gfp); 3128c3e34a4SDavid Howells if (ret < 0) { 3138c3e34a4SDavid Howells kmem_cache_free(rxrpc_call_jar, call); 3148c3e34a4SDavid Howells return ERR_PTR(ret); 3158c3e34a4SDavid Howells } 3168c3e34a4SDavid Howells 3178c3e34a4SDavid Howells /* Record copies of information for hashtable lookup */ 31819ffa01cSDavid Howells call->family = rx->family; 31919ffa01cSDavid Howells call->local = call->conn->params.local; 32019ffa01cSDavid Howells switch (call->family) { 3218c3e34a4SDavid Howells case AF_INET: 3228c3e34a4SDavid Howells call->peer_ip.ipv4_addr = 3238c3e34a4SDavid Howells trans->peer->srx.transport.sin.sin_addr.s_addr; 3248c3e34a4SDavid Howells break; 3258c3e34a4SDavid Howells case AF_INET6: 3268c3e34a4SDavid Howells memcpy(call->peer_ip.ipv6_addr, 3278c3e34a4SDavid Howells trans->peer->srx.transport.sin6.sin6_addr.in6_u.u6_addr8, 3288c3e34a4SDavid Howells sizeof(call->peer_ip.ipv6_addr)); 3298c3e34a4SDavid Howells break; 3308c3e34a4SDavid Howells } 33119ffa01cSDavid Howells call->epoch = call->conn->proto.epoch; 33219ffa01cSDavid Howells call->service_id = call->conn->params.service_id; 33319ffa01cSDavid Howells call->in_clientflag = call->conn->proto.in_clientflag; 3348c3e34a4SDavid Howells /* Add the new call to the hashtable */ 3358c3e34a4SDavid Howells rxrpc_call_hash_add(call); 3368c3e34a4SDavid Howells 3378c3e34a4SDavid Howells spin_lock(&call->conn->trans->peer->lock); 338f66d7490SDavid Howells hlist_add_head(&call->error_link, &call->conn->trans->peer->error_targets); 3398c3e34a4SDavid Howells spin_unlock(&call->conn->trans->peer->lock); 3408c3e34a4SDavid Howells 3418c3e34a4SDavid Howells call->lifetimer.expires = jiffies + rxrpc_max_call_lifetime; 3428c3e34a4SDavid Howells add_timer(&call->lifetimer); 3438c3e34a4SDavid Howells 3448c3e34a4SDavid Howells _leave(" = %p", call); 3458c3e34a4SDavid Howells return call; 3468c3e34a4SDavid Howells } 3478c3e34a4SDavid Howells 3488c3e34a4SDavid Howells /* 3498c3e34a4SDavid Howells * set up a call for the given data 3508c3e34a4SDavid Howells * - called in process context with IRQs enabled 3518c3e34a4SDavid Howells */ 3528c3e34a4SDavid Howells struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, 35319ffa01cSDavid Howells struct rxrpc_conn_parameters *cp, 3548c3e34a4SDavid Howells struct rxrpc_transport *trans, 3558c3e34a4SDavid Howells struct rxrpc_conn_bundle *bundle, 3568c3e34a4SDavid Howells unsigned long user_call_ID, 3578c3e34a4SDavid Howells gfp_t gfp) 3588c3e34a4SDavid Howells { 3598c3e34a4SDavid Howells struct rxrpc_call *call, *xcall; 3608c3e34a4SDavid Howells struct rb_node *parent, **pp; 3618c3e34a4SDavid Howells 3628c3e34a4SDavid Howells _enter("%p,%d,%d,%lx", 3638c3e34a4SDavid Howells rx, trans->debug_id, bundle ? bundle->debug_id : -1, 3648c3e34a4SDavid Howells user_call_ID); 3658c3e34a4SDavid Howells 36619ffa01cSDavid Howells call = rxrpc_alloc_client_call(rx, cp, trans, bundle, gfp); 3678c3e34a4SDavid Howells if (IS_ERR(call)) { 3688c3e34a4SDavid Howells _leave(" = %ld", PTR_ERR(call)); 3698c3e34a4SDavid Howells return call; 3708c3e34a4SDavid Howells } 3718c3e34a4SDavid Howells 3728c3e34a4SDavid Howells call->user_call_ID = user_call_ID; 3738c3e34a4SDavid Howells __set_bit(RXRPC_CALL_HAS_USERID, &call->flags); 3748c3e34a4SDavid Howells 3758c3e34a4SDavid Howells write_lock(&rx->call_lock); 3768c3e34a4SDavid Howells 3778c3e34a4SDavid Howells pp = &rx->calls.rb_node; 3788c3e34a4SDavid Howells parent = NULL; 3798c3e34a4SDavid Howells while (*pp) { 3808c3e34a4SDavid Howells parent = *pp; 3818c3e34a4SDavid Howells xcall = rb_entry(parent, struct rxrpc_call, sock_node); 3828c3e34a4SDavid Howells 3838c3e34a4SDavid Howells if (user_call_ID < xcall->user_call_ID) 3848c3e34a4SDavid Howells pp = &(*pp)->rb_left; 3858c3e34a4SDavid Howells else if (user_call_ID > xcall->user_call_ID) 3868c3e34a4SDavid Howells pp = &(*pp)->rb_right; 3878c3e34a4SDavid Howells else 3888c3e34a4SDavid Howells goto found_user_ID_now_present; 3898c3e34a4SDavid Howells } 3908c3e34a4SDavid Howells 3918c3e34a4SDavid Howells rxrpc_get_call(call); 3928c3e34a4SDavid Howells 3938c3e34a4SDavid Howells rb_link_node(&call->sock_node, parent, pp); 3948c3e34a4SDavid Howells rb_insert_color(&call->sock_node, &rx->calls); 3958c3e34a4SDavid Howells write_unlock(&rx->call_lock); 3968c3e34a4SDavid Howells 3978c3e34a4SDavid Howells write_lock_bh(&rxrpc_call_lock); 3988c3e34a4SDavid Howells list_add_tail(&call->link, &rxrpc_calls); 3998c3e34a4SDavid Howells write_unlock_bh(&rxrpc_call_lock); 4008c3e34a4SDavid Howells 4018c3e34a4SDavid Howells _net("CALL new %d on CONN %d", call->debug_id, call->conn->debug_id); 4028c3e34a4SDavid Howells 4038c3e34a4SDavid Howells _leave(" = %p [new]", call); 4048c3e34a4SDavid Howells return call; 4058c3e34a4SDavid Howells 4068c3e34a4SDavid Howells /* We unexpectedly found the user ID in the list after taking 4078c3e34a4SDavid Howells * the call_lock. This shouldn't happen unless the user races 4088c3e34a4SDavid Howells * with itself and tries to add the same user ID twice at the 4098c3e34a4SDavid Howells * same time in different threads. 4108c3e34a4SDavid Howells */ 4118c3e34a4SDavid Howells found_user_ID_now_present: 4128c3e34a4SDavid Howells write_unlock(&rx->call_lock); 4138c3e34a4SDavid Howells rxrpc_put_call(call); 4148c3e34a4SDavid Howells _leave(" = -EEXIST [%p]", call); 4158c3e34a4SDavid Howells return ERR_PTR(-EEXIST); 4168c3e34a4SDavid Howells } 4178c3e34a4SDavid Howells 4188c3e34a4SDavid Howells /* 4198c3e34a4SDavid Howells * set up an incoming call 4208c3e34a4SDavid Howells * - called in process context with IRQs enabled 4218c3e34a4SDavid Howells */ 4228c3e34a4SDavid Howells struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx, 4238c3e34a4SDavid Howells struct rxrpc_connection *conn, 4248c3e34a4SDavid Howells struct rxrpc_host_header *hdr) 4258c3e34a4SDavid Howells { 4268c3e34a4SDavid Howells struct rxrpc_call *call, *candidate; 4278c3e34a4SDavid Howells struct rb_node **p, *parent; 4288c3e34a4SDavid Howells u32 call_id; 4298c3e34a4SDavid Howells 4308c3e34a4SDavid Howells _enter(",%d", conn->debug_id); 4318c3e34a4SDavid Howells 4328c3e34a4SDavid Howells ASSERT(rx != NULL); 4338c3e34a4SDavid Howells 4348c3e34a4SDavid Howells candidate = rxrpc_alloc_call(GFP_NOIO); 4358c3e34a4SDavid Howells if (!candidate) 4368c3e34a4SDavid Howells return ERR_PTR(-EBUSY); 4378c3e34a4SDavid Howells 4388c3e34a4SDavid Howells candidate->socket = rx; 4398c3e34a4SDavid Howells candidate->conn = conn; 4408c3e34a4SDavid Howells candidate->cid = hdr->cid; 4418c3e34a4SDavid Howells candidate->call_id = hdr->callNumber; 4428c3e34a4SDavid Howells candidate->channel = hdr->cid & RXRPC_CHANNELMASK; 4438c3e34a4SDavid Howells candidate->rx_data_post = 0; 4448c3e34a4SDavid Howells candidate->state = RXRPC_CALL_SERVER_ACCEPTING; 4458c3e34a4SDavid Howells if (conn->security_ix > 0) 4468c3e34a4SDavid Howells candidate->state = RXRPC_CALL_SERVER_SECURING; 4478c3e34a4SDavid Howells 4488c3e34a4SDavid Howells write_lock_bh(&conn->lock); 4498c3e34a4SDavid Howells 4508c3e34a4SDavid Howells /* set the channel for this call */ 4518c3e34a4SDavid Howells call = conn->channels[candidate->channel]; 4528c3e34a4SDavid Howells _debug("channel[%u] is %p", candidate->channel, call); 4538c3e34a4SDavid Howells if (call && call->call_id == hdr->callNumber) { 4548c3e34a4SDavid Howells /* already set; must've been a duplicate packet */ 4558c3e34a4SDavid Howells _debug("extant call [%d]", call->state); 4568c3e34a4SDavid Howells ASSERTCMP(call->conn, ==, conn); 4578c3e34a4SDavid Howells 4588c3e34a4SDavid Howells read_lock(&call->state_lock); 4598c3e34a4SDavid Howells switch (call->state) { 4608c3e34a4SDavid Howells case RXRPC_CALL_LOCALLY_ABORTED: 4618c3e34a4SDavid Howells if (!test_and_set_bit(RXRPC_CALL_EV_ABORT, &call->events)) 4628c3e34a4SDavid Howells rxrpc_queue_call(call); 4638c3e34a4SDavid Howells case RXRPC_CALL_REMOTELY_ABORTED: 4648c3e34a4SDavid Howells read_unlock(&call->state_lock); 4658c3e34a4SDavid Howells goto aborted_call; 4668c3e34a4SDavid Howells default: 4678c3e34a4SDavid Howells rxrpc_get_call(call); 4688c3e34a4SDavid Howells read_unlock(&call->state_lock); 4698c3e34a4SDavid Howells goto extant_call; 4708c3e34a4SDavid Howells } 4718c3e34a4SDavid Howells } 4728c3e34a4SDavid Howells 4738c3e34a4SDavid Howells if (call) { 4748c3e34a4SDavid Howells /* it seems the channel is still in use from the previous call 4758c3e34a4SDavid Howells * - ditch the old binding if its call is now complete */ 4768c3e34a4SDavid Howells _debug("CALL: %u { %s }", 4778c3e34a4SDavid Howells call->debug_id, rxrpc_call_states[call->state]); 4788c3e34a4SDavid Howells 4798c3e34a4SDavid Howells if (call->state >= RXRPC_CALL_COMPLETE) { 4808c3e34a4SDavid Howells conn->channels[call->channel] = NULL; 4818c3e34a4SDavid Howells } else { 4828c3e34a4SDavid Howells write_unlock_bh(&conn->lock); 4838c3e34a4SDavid Howells kmem_cache_free(rxrpc_call_jar, candidate); 4848c3e34a4SDavid Howells _leave(" = -EBUSY"); 4858c3e34a4SDavid Howells return ERR_PTR(-EBUSY); 4868c3e34a4SDavid Howells } 4878c3e34a4SDavid Howells } 4888c3e34a4SDavid Howells 4898c3e34a4SDavid Howells /* check the call number isn't duplicate */ 4908c3e34a4SDavid Howells _debug("check dup"); 4918c3e34a4SDavid Howells call_id = hdr->callNumber; 4928c3e34a4SDavid Howells p = &conn->calls.rb_node; 4938c3e34a4SDavid Howells parent = NULL; 4948c3e34a4SDavid Howells while (*p) { 4958c3e34a4SDavid Howells parent = *p; 4968c3e34a4SDavid Howells call = rb_entry(parent, struct rxrpc_call, conn_node); 4978c3e34a4SDavid Howells 4988c3e34a4SDavid Howells /* The tree is sorted in order of the __be32 value without 4998c3e34a4SDavid Howells * turning it into host order. 5008c3e34a4SDavid Howells */ 5018c3e34a4SDavid Howells if (call_id < call->call_id) 5028c3e34a4SDavid Howells p = &(*p)->rb_left; 5038c3e34a4SDavid Howells else if (call_id > call->call_id) 5048c3e34a4SDavid Howells p = &(*p)->rb_right; 5058c3e34a4SDavid Howells else 5068c3e34a4SDavid Howells goto old_call; 5078c3e34a4SDavid Howells } 5088c3e34a4SDavid Howells 5098c3e34a4SDavid Howells /* make the call available */ 5108c3e34a4SDavid Howells _debug("new call"); 5118c3e34a4SDavid Howells call = candidate; 5128c3e34a4SDavid Howells candidate = NULL; 5138c3e34a4SDavid Howells rb_link_node(&call->conn_node, parent, p); 5148c3e34a4SDavid Howells rb_insert_color(&call->conn_node, &conn->calls); 5158c3e34a4SDavid Howells conn->channels[call->channel] = call; 5168c3e34a4SDavid Howells sock_hold(&rx->sk); 5178c3e34a4SDavid Howells atomic_inc(&conn->usage); 5188c3e34a4SDavid Howells write_unlock_bh(&conn->lock); 5198c3e34a4SDavid Howells 5208c3e34a4SDavid Howells spin_lock(&conn->trans->peer->lock); 521f66d7490SDavid Howells hlist_add_head(&call->error_link, &conn->trans->peer->error_targets); 5228c3e34a4SDavid Howells spin_unlock(&conn->trans->peer->lock); 5238c3e34a4SDavid Howells 5248c3e34a4SDavid Howells write_lock_bh(&rxrpc_call_lock); 5258c3e34a4SDavid Howells list_add_tail(&call->link, &rxrpc_calls); 5268c3e34a4SDavid Howells write_unlock_bh(&rxrpc_call_lock); 5278c3e34a4SDavid Howells 5288c3e34a4SDavid Howells /* Record copies of information for hashtable lookup */ 52919ffa01cSDavid Howells call->family = rx->family; 5308c3e34a4SDavid Howells call->local = conn->trans->local; 53119ffa01cSDavid Howells switch (call->family) { 5328c3e34a4SDavid Howells case AF_INET: 5338c3e34a4SDavid Howells call->peer_ip.ipv4_addr = 5348c3e34a4SDavid Howells conn->trans->peer->srx.transport.sin.sin_addr.s_addr; 5358c3e34a4SDavid Howells break; 5368c3e34a4SDavid Howells case AF_INET6: 5378c3e34a4SDavid Howells memcpy(call->peer_ip.ipv6_addr, 5388c3e34a4SDavid Howells conn->trans->peer->srx.transport.sin6.sin6_addr.in6_u.u6_addr8, 5398c3e34a4SDavid Howells sizeof(call->peer_ip.ipv6_addr)); 5408c3e34a4SDavid Howells break; 5418c3e34a4SDavid Howells default: 5428c3e34a4SDavid Howells break; 5438c3e34a4SDavid Howells } 54419ffa01cSDavid Howells call->epoch = conn->proto.epoch; 54519ffa01cSDavid Howells call->service_id = conn->params.service_id; 54619ffa01cSDavid Howells call->in_clientflag = conn->proto.in_clientflag; 5478c3e34a4SDavid Howells /* Add the new call to the hashtable */ 5488c3e34a4SDavid Howells rxrpc_call_hash_add(call); 5498c3e34a4SDavid Howells 5508c3e34a4SDavid Howells _net("CALL incoming %d on CONN %d", call->debug_id, call->conn->debug_id); 5518c3e34a4SDavid Howells 5528c3e34a4SDavid Howells call->lifetimer.expires = jiffies + rxrpc_max_call_lifetime; 5538c3e34a4SDavid Howells add_timer(&call->lifetimer); 5548c3e34a4SDavid Howells _leave(" = %p {%d} [new]", call, call->debug_id); 5558c3e34a4SDavid Howells return call; 5568c3e34a4SDavid Howells 5578c3e34a4SDavid Howells extant_call: 5588c3e34a4SDavid Howells write_unlock_bh(&conn->lock); 5598c3e34a4SDavid Howells kmem_cache_free(rxrpc_call_jar, candidate); 5608c3e34a4SDavid Howells _leave(" = %p {%d} [extant]", call, call ? call->debug_id : -1); 5618c3e34a4SDavid Howells return call; 5628c3e34a4SDavid Howells 5638c3e34a4SDavid Howells aborted_call: 5648c3e34a4SDavid Howells write_unlock_bh(&conn->lock); 5658c3e34a4SDavid Howells kmem_cache_free(rxrpc_call_jar, candidate); 5668c3e34a4SDavid Howells _leave(" = -ECONNABORTED"); 5678c3e34a4SDavid Howells return ERR_PTR(-ECONNABORTED); 5688c3e34a4SDavid Howells 5698c3e34a4SDavid Howells old_call: 5708c3e34a4SDavid Howells write_unlock_bh(&conn->lock); 5718c3e34a4SDavid Howells kmem_cache_free(rxrpc_call_jar, candidate); 5728c3e34a4SDavid Howells _leave(" = -ECONNRESET [old]"); 5738c3e34a4SDavid Howells return ERR_PTR(-ECONNRESET); 5748c3e34a4SDavid Howells } 5758c3e34a4SDavid Howells 5768c3e34a4SDavid Howells /* 5778c3e34a4SDavid Howells * detach a call from a socket and set up for release 5788c3e34a4SDavid Howells */ 5798c3e34a4SDavid Howells void rxrpc_release_call(struct rxrpc_call *call) 5808c3e34a4SDavid Howells { 5818c3e34a4SDavid Howells struct rxrpc_connection *conn = call->conn; 5828c3e34a4SDavid Howells struct rxrpc_sock *rx = call->socket; 5838c3e34a4SDavid Howells 5848c3e34a4SDavid Howells _enter("{%d,%d,%d,%d}", 5858c3e34a4SDavid Howells call->debug_id, atomic_read(&call->usage), 5868c3e34a4SDavid Howells atomic_read(&call->ackr_not_idle), 5878c3e34a4SDavid Howells call->rx_first_oos); 5888c3e34a4SDavid Howells 5898c3e34a4SDavid Howells spin_lock_bh(&call->lock); 5908c3e34a4SDavid Howells if (test_and_set_bit(RXRPC_CALL_RELEASED, &call->flags)) 5918c3e34a4SDavid Howells BUG(); 5928c3e34a4SDavid Howells spin_unlock_bh(&call->lock); 5938c3e34a4SDavid Howells 5948c3e34a4SDavid Howells /* dissociate from the socket 5958c3e34a4SDavid Howells * - the socket's ref on the call is passed to the death timer 5968c3e34a4SDavid Howells */ 5978c3e34a4SDavid Howells _debug("RELEASE CALL %p (%d CONN %p)", call, call->debug_id, conn); 5988c3e34a4SDavid Howells 5998c3e34a4SDavid Howells write_lock_bh(&rx->call_lock); 6008c3e34a4SDavid Howells if (!list_empty(&call->accept_link)) { 6018c3e34a4SDavid Howells _debug("unlinking once-pending call %p { e=%lx f=%lx }", 6028c3e34a4SDavid Howells call, call->events, call->flags); 6038c3e34a4SDavid Howells ASSERT(!test_bit(RXRPC_CALL_HAS_USERID, &call->flags)); 6048c3e34a4SDavid Howells list_del_init(&call->accept_link); 6058c3e34a4SDavid Howells sk_acceptq_removed(&rx->sk); 6068c3e34a4SDavid Howells } else if (test_bit(RXRPC_CALL_HAS_USERID, &call->flags)) { 6078c3e34a4SDavid Howells rb_erase(&call->sock_node, &rx->calls); 6088c3e34a4SDavid Howells memset(&call->sock_node, 0xdd, sizeof(call->sock_node)); 6098c3e34a4SDavid Howells clear_bit(RXRPC_CALL_HAS_USERID, &call->flags); 6108c3e34a4SDavid Howells } 6118c3e34a4SDavid Howells write_unlock_bh(&rx->call_lock); 6128c3e34a4SDavid Howells 6138c3e34a4SDavid Howells /* free up the channel for reuse */ 6148c3e34a4SDavid Howells spin_lock(&conn->trans->client_lock); 6158c3e34a4SDavid Howells write_lock_bh(&conn->lock); 6168c3e34a4SDavid Howells write_lock(&call->state_lock); 6178c3e34a4SDavid Howells 6188c3e34a4SDavid Howells if (conn->channels[call->channel] == call) 6198c3e34a4SDavid Howells conn->channels[call->channel] = NULL; 6208c3e34a4SDavid Howells 6218c3e34a4SDavid Howells if (conn->out_clientflag && conn->bundle) { 6228c3e34a4SDavid Howells conn->avail_calls++; 6238c3e34a4SDavid Howells switch (conn->avail_calls) { 6248c3e34a4SDavid Howells case 1: 6258c3e34a4SDavid Howells list_move_tail(&conn->bundle_link, 6268c3e34a4SDavid Howells &conn->bundle->avail_conns); 6278c3e34a4SDavid Howells case 2 ... RXRPC_MAXCALLS - 1: 6288c3e34a4SDavid Howells ASSERT(conn->channels[0] == NULL || 6298c3e34a4SDavid Howells conn->channels[1] == NULL || 6308c3e34a4SDavid Howells conn->channels[2] == NULL || 6318c3e34a4SDavid Howells conn->channels[3] == NULL); 6328c3e34a4SDavid Howells break; 6338c3e34a4SDavid Howells case RXRPC_MAXCALLS: 6348c3e34a4SDavid Howells list_move_tail(&conn->bundle_link, 6358c3e34a4SDavid Howells &conn->bundle->unused_conns); 6368c3e34a4SDavid Howells ASSERT(conn->channels[0] == NULL && 6378c3e34a4SDavid Howells conn->channels[1] == NULL && 6388c3e34a4SDavid Howells conn->channels[2] == NULL && 6398c3e34a4SDavid Howells conn->channels[3] == NULL); 6408c3e34a4SDavid Howells break; 6418c3e34a4SDavid Howells default: 6428c3e34a4SDavid Howells pr_err("conn->avail_calls=%d\n", conn->avail_calls); 6438c3e34a4SDavid Howells BUG(); 6448c3e34a4SDavid Howells } 6458c3e34a4SDavid Howells } 6468c3e34a4SDavid Howells 6478c3e34a4SDavid Howells spin_unlock(&conn->trans->client_lock); 6488c3e34a4SDavid Howells 6498c3e34a4SDavid Howells if (call->state < RXRPC_CALL_COMPLETE && 6508c3e34a4SDavid Howells call->state != RXRPC_CALL_CLIENT_FINAL_ACK) { 6518c3e34a4SDavid Howells _debug("+++ ABORTING STATE %d +++\n", call->state); 6528c3e34a4SDavid Howells call->state = RXRPC_CALL_LOCALLY_ABORTED; 6538c3e34a4SDavid Howells call->local_abort = RX_CALL_DEAD; 6548c3e34a4SDavid Howells set_bit(RXRPC_CALL_EV_ABORT, &call->events); 6558c3e34a4SDavid Howells rxrpc_queue_call(call); 6568c3e34a4SDavid Howells } 6578c3e34a4SDavid Howells write_unlock(&call->state_lock); 6588c3e34a4SDavid Howells write_unlock_bh(&conn->lock); 6598c3e34a4SDavid Howells 6608c3e34a4SDavid Howells /* clean up the Rx queue */ 6618c3e34a4SDavid Howells if (!skb_queue_empty(&call->rx_queue) || 6628c3e34a4SDavid Howells !skb_queue_empty(&call->rx_oos_queue)) { 6638c3e34a4SDavid Howells struct rxrpc_skb_priv *sp; 6648c3e34a4SDavid Howells struct sk_buff *skb; 6658c3e34a4SDavid Howells 6668c3e34a4SDavid Howells _debug("purge Rx queues"); 6678c3e34a4SDavid Howells 6688c3e34a4SDavid Howells spin_lock_bh(&call->lock); 6698c3e34a4SDavid Howells while ((skb = skb_dequeue(&call->rx_queue)) || 6708c3e34a4SDavid Howells (skb = skb_dequeue(&call->rx_oos_queue))) { 6718c3e34a4SDavid Howells sp = rxrpc_skb(skb); 6728c3e34a4SDavid Howells if (sp->call) { 6738c3e34a4SDavid Howells ASSERTCMP(sp->call, ==, call); 6748c3e34a4SDavid Howells rxrpc_put_call(call); 6758c3e34a4SDavid Howells sp->call = NULL; 6768c3e34a4SDavid Howells } 6778c3e34a4SDavid Howells skb->destructor = NULL; 6788c3e34a4SDavid Howells spin_unlock_bh(&call->lock); 6798c3e34a4SDavid Howells 6808c3e34a4SDavid Howells _debug("- zap %s %%%u #%u", 6818c3e34a4SDavid Howells rxrpc_pkts[sp->hdr.type], 6828c3e34a4SDavid Howells sp->hdr.serial, sp->hdr.seq); 6838c3e34a4SDavid Howells rxrpc_free_skb(skb); 6848c3e34a4SDavid Howells spin_lock_bh(&call->lock); 6858c3e34a4SDavid Howells } 6868c3e34a4SDavid Howells spin_unlock_bh(&call->lock); 6878c3e34a4SDavid Howells 6888c3e34a4SDavid Howells ASSERTCMP(call->state, !=, RXRPC_CALL_COMPLETE); 6898c3e34a4SDavid Howells } 6908c3e34a4SDavid Howells 6918c3e34a4SDavid Howells del_timer_sync(&call->resend_timer); 6928c3e34a4SDavid Howells del_timer_sync(&call->ack_timer); 6938c3e34a4SDavid Howells del_timer_sync(&call->lifetimer); 6948c3e34a4SDavid Howells call->deadspan.expires = jiffies + rxrpc_dead_call_expiry; 6958c3e34a4SDavid Howells add_timer(&call->deadspan); 6968c3e34a4SDavid Howells 6978c3e34a4SDavid Howells _leave(""); 6988c3e34a4SDavid Howells } 6998c3e34a4SDavid Howells 7008c3e34a4SDavid Howells /* 7018c3e34a4SDavid Howells * handle a dead call being ready for reaping 7028c3e34a4SDavid Howells */ 7038c3e34a4SDavid Howells static void rxrpc_dead_call_expired(unsigned long _call) 7048c3e34a4SDavid Howells { 7058c3e34a4SDavid Howells struct rxrpc_call *call = (struct rxrpc_call *) _call; 7068c3e34a4SDavid Howells 7078c3e34a4SDavid Howells _enter("{%d}", call->debug_id); 7088c3e34a4SDavid Howells 7098c3e34a4SDavid Howells write_lock_bh(&call->state_lock); 7108c3e34a4SDavid Howells call->state = RXRPC_CALL_DEAD; 7118c3e34a4SDavid Howells write_unlock_bh(&call->state_lock); 7128c3e34a4SDavid Howells rxrpc_put_call(call); 7138c3e34a4SDavid Howells } 7148c3e34a4SDavid Howells 7158c3e34a4SDavid Howells /* 7168c3e34a4SDavid Howells * mark a call as to be released, aborting it if it's still in progress 7178c3e34a4SDavid Howells * - called with softirqs disabled 7188c3e34a4SDavid Howells */ 7198c3e34a4SDavid Howells static void rxrpc_mark_call_released(struct rxrpc_call *call) 7208c3e34a4SDavid Howells { 7218c3e34a4SDavid Howells bool sched; 7228c3e34a4SDavid Howells 7238c3e34a4SDavid Howells write_lock(&call->state_lock); 7248c3e34a4SDavid Howells if (call->state < RXRPC_CALL_DEAD) { 7258c3e34a4SDavid Howells sched = false; 7268c3e34a4SDavid Howells if (call->state < RXRPC_CALL_COMPLETE) { 7278c3e34a4SDavid Howells _debug("abort call %p", call); 7288c3e34a4SDavid Howells call->state = RXRPC_CALL_LOCALLY_ABORTED; 7298c3e34a4SDavid Howells call->local_abort = RX_CALL_DEAD; 7308c3e34a4SDavid Howells if (!test_and_set_bit(RXRPC_CALL_EV_ABORT, &call->events)) 7318c3e34a4SDavid Howells sched = true; 7328c3e34a4SDavid Howells } 7338c3e34a4SDavid Howells if (!test_and_set_bit(RXRPC_CALL_EV_RELEASE, &call->events)) 7348c3e34a4SDavid Howells sched = true; 7358c3e34a4SDavid Howells if (sched) 7368c3e34a4SDavid Howells rxrpc_queue_call(call); 7378c3e34a4SDavid Howells } 7388c3e34a4SDavid Howells write_unlock(&call->state_lock); 7398c3e34a4SDavid Howells } 7408c3e34a4SDavid Howells 7418c3e34a4SDavid Howells /* 7428c3e34a4SDavid Howells * release all the calls associated with a socket 7438c3e34a4SDavid Howells */ 7448c3e34a4SDavid Howells void rxrpc_release_calls_on_socket(struct rxrpc_sock *rx) 7458c3e34a4SDavid Howells { 7468c3e34a4SDavid Howells struct rxrpc_call *call; 7478c3e34a4SDavid Howells struct rb_node *p; 7488c3e34a4SDavid Howells 7498c3e34a4SDavid Howells _enter("%p", rx); 7508c3e34a4SDavid Howells 7518c3e34a4SDavid Howells read_lock_bh(&rx->call_lock); 7528c3e34a4SDavid Howells 7538c3e34a4SDavid Howells /* mark all the calls as no longer wanting incoming packets */ 7548c3e34a4SDavid Howells for (p = rb_first(&rx->calls); p; p = rb_next(p)) { 7558c3e34a4SDavid Howells call = rb_entry(p, struct rxrpc_call, sock_node); 7568c3e34a4SDavid Howells rxrpc_mark_call_released(call); 7578c3e34a4SDavid Howells } 7588c3e34a4SDavid Howells 7598c3e34a4SDavid Howells /* kill the not-yet-accepted incoming calls */ 7608c3e34a4SDavid Howells list_for_each_entry(call, &rx->secureq, accept_link) { 7618c3e34a4SDavid Howells rxrpc_mark_call_released(call); 7628c3e34a4SDavid Howells } 7638c3e34a4SDavid Howells 7648c3e34a4SDavid Howells list_for_each_entry(call, &rx->acceptq, accept_link) { 7658c3e34a4SDavid Howells rxrpc_mark_call_released(call); 7668c3e34a4SDavid Howells } 7678c3e34a4SDavid Howells 7688c3e34a4SDavid Howells read_unlock_bh(&rx->call_lock); 7698c3e34a4SDavid Howells _leave(""); 7708c3e34a4SDavid Howells } 7718c3e34a4SDavid Howells 7728c3e34a4SDavid Howells /* 7738c3e34a4SDavid Howells * release a call 7748c3e34a4SDavid Howells */ 7758c3e34a4SDavid Howells void __rxrpc_put_call(struct rxrpc_call *call) 7768c3e34a4SDavid Howells { 7778c3e34a4SDavid Howells ASSERT(call != NULL); 7788c3e34a4SDavid Howells 7798c3e34a4SDavid Howells _enter("%p{u=%d}", call, atomic_read(&call->usage)); 7808c3e34a4SDavid Howells 7818c3e34a4SDavid Howells ASSERTCMP(atomic_read(&call->usage), >, 0); 7828c3e34a4SDavid Howells 7838c3e34a4SDavid Howells if (atomic_dec_and_test(&call->usage)) { 7848c3e34a4SDavid Howells _debug("call %d dead", call->debug_id); 7858c3e34a4SDavid Howells ASSERTCMP(call->state, ==, RXRPC_CALL_DEAD); 7868c3e34a4SDavid Howells rxrpc_queue_work(&call->destroyer); 7878c3e34a4SDavid Howells } 7888c3e34a4SDavid Howells _leave(""); 7898c3e34a4SDavid Howells } 7908c3e34a4SDavid Howells 7918c3e34a4SDavid Howells /* 7928c3e34a4SDavid Howells * clean up a call 7938c3e34a4SDavid Howells */ 7948c3e34a4SDavid Howells static void rxrpc_cleanup_call(struct rxrpc_call *call) 7958c3e34a4SDavid Howells { 7968c3e34a4SDavid Howells _net("DESTROY CALL %d", call->debug_id); 7978c3e34a4SDavid Howells 7988c3e34a4SDavid Howells ASSERT(call->socket); 7998c3e34a4SDavid Howells 8008c3e34a4SDavid Howells memset(&call->sock_node, 0xcd, sizeof(call->sock_node)); 8018c3e34a4SDavid Howells 8028c3e34a4SDavid Howells del_timer_sync(&call->lifetimer); 8038c3e34a4SDavid Howells del_timer_sync(&call->deadspan); 8048c3e34a4SDavid Howells del_timer_sync(&call->ack_timer); 8058c3e34a4SDavid Howells del_timer_sync(&call->resend_timer); 8068c3e34a4SDavid Howells 8078c3e34a4SDavid Howells ASSERT(test_bit(RXRPC_CALL_RELEASED, &call->flags)); 8088c3e34a4SDavid Howells ASSERTCMP(call->events, ==, 0); 8098c3e34a4SDavid Howells if (work_pending(&call->processor)) { 8108c3e34a4SDavid Howells _debug("defer destroy"); 8118c3e34a4SDavid Howells rxrpc_queue_work(&call->destroyer); 8128c3e34a4SDavid Howells return; 8138c3e34a4SDavid Howells } 8148c3e34a4SDavid Howells 8158c3e34a4SDavid Howells if (call->conn) { 8168c3e34a4SDavid Howells spin_lock(&call->conn->trans->peer->lock); 817f66d7490SDavid Howells hlist_del_init(&call->error_link); 8188c3e34a4SDavid Howells spin_unlock(&call->conn->trans->peer->lock); 8198c3e34a4SDavid Howells 8208c3e34a4SDavid Howells write_lock_bh(&call->conn->lock); 8218c3e34a4SDavid Howells rb_erase(&call->conn_node, &call->conn->calls); 8228c3e34a4SDavid Howells write_unlock_bh(&call->conn->lock); 8238c3e34a4SDavid Howells rxrpc_put_connection(call->conn); 8248c3e34a4SDavid Howells } 8258c3e34a4SDavid Howells 8268c3e34a4SDavid Howells /* Remove the call from the hash */ 8278c3e34a4SDavid Howells rxrpc_call_hash_del(call); 8288c3e34a4SDavid Howells 8298c3e34a4SDavid Howells if (call->acks_window) { 8308c3e34a4SDavid Howells _debug("kill Tx window %d", 8318c3e34a4SDavid Howells CIRC_CNT(call->acks_head, call->acks_tail, 8328c3e34a4SDavid Howells call->acks_winsz)); 8338c3e34a4SDavid Howells smp_mb(); 8348c3e34a4SDavid Howells while (CIRC_CNT(call->acks_head, call->acks_tail, 8358c3e34a4SDavid Howells call->acks_winsz) > 0) { 8368c3e34a4SDavid Howells struct rxrpc_skb_priv *sp; 8378c3e34a4SDavid Howells unsigned long _skb; 8388c3e34a4SDavid Howells 8398c3e34a4SDavid Howells _skb = call->acks_window[call->acks_tail] & ~1; 8408c3e34a4SDavid Howells sp = rxrpc_skb((struct sk_buff *)_skb); 8418c3e34a4SDavid Howells _debug("+++ clear Tx %u", sp->hdr.seq); 8428c3e34a4SDavid Howells rxrpc_free_skb((struct sk_buff *)_skb); 8438c3e34a4SDavid Howells call->acks_tail = 8448c3e34a4SDavid Howells (call->acks_tail + 1) & (call->acks_winsz - 1); 8458c3e34a4SDavid Howells } 8468c3e34a4SDavid Howells 8478c3e34a4SDavid Howells kfree(call->acks_window); 8488c3e34a4SDavid Howells } 8498c3e34a4SDavid Howells 8508c3e34a4SDavid Howells rxrpc_free_skb(call->tx_pending); 8518c3e34a4SDavid Howells 8528c3e34a4SDavid Howells rxrpc_purge_queue(&call->rx_queue); 8538c3e34a4SDavid Howells ASSERT(skb_queue_empty(&call->rx_oos_queue)); 8548c3e34a4SDavid Howells sock_put(&call->socket->sk); 8558c3e34a4SDavid Howells kmem_cache_free(rxrpc_call_jar, call); 8568c3e34a4SDavid Howells } 8578c3e34a4SDavid Howells 8588c3e34a4SDavid Howells /* 8598c3e34a4SDavid Howells * destroy a call 8608c3e34a4SDavid Howells */ 8618c3e34a4SDavid Howells static void rxrpc_destroy_call(struct work_struct *work) 8628c3e34a4SDavid Howells { 8638c3e34a4SDavid Howells struct rxrpc_call *call = 8648c3e34a4SDavid Howells container_of(work, struct rxrpc_call, destroyer); 8658c3e34a4SDavid Howells 8668c3e34a4SDavid Howells _enter("%p{%d,%d,%p}", 8678c3e34a4SDavid Howells call, atomic_read(&call->usage), call->channel, call->conn); 8688c3e34a4SDavid Howells 8698c3e34a4SDavid Howells ASSERTCMP(call->state, ==, RXRPC_CALL_DEAD); 8708c3e34a4SDavid Howells 8718c3e34a4SDavid Howells write_lock_bh(&rxrpc_call_lock); 8728c3e34a4SDavid Howells list_del_init(&call->link); 8738c3e34a4SDavid Howells write_unlock_bh(&rxrpc_call_lock); 8748c3e34a4SDavid Howells 8758c3e34a4SDavid Howells rxrpc_cleanup_call(call); 8768c3e34a4SDavid Howells _leave(""); 8778c3e34a4SDavid Howells } 8788c3e34a4SDavid Howells 8798c3e34a4SDavid Howells /* 8808c3e34a4SDavid Howells * preemptively destroy all the call records from a transport endpoint rather 8818c3e34a4SDavid Howells * than waiting for them to time out 8828c3e34a4SDavid Howells */ 8838c3e34a4SDavid Howells void __exit rxrpc_destroy_all_calls(void) 8848c3e34a4SDavid Howells { 8858c3e34a4SDavid Howells struct rxrpc_call *call; 8868c3e34a4SDavid Howells 8878c3e34a4SDavid Howells _enter(""); 8888c3e34a4SDavid Howells write_lock_bh(&rxrpc_call_lock); 8898c3e34a4SDavid Howells 8908c3e34a4SDavid Howells while (!list_empty(&rxrpc_calls)) { 8918c3e34a4SDavid Howells call = list_entry(rxrpc_calls.next, struct rxrpc_call, link); 8928c3e34a4SDavid Howells _debug("Zapping call %p", call); 8938c3e34a4SDavid Howells 8948c3e34a4SDavid Howells list_del_init(&call->link); 8958c3e34a4SDavid Howells 8968c3e34a4SDavid Howells switch (atomic_read(&call->usage)) { 8978c3e34a4SDavid Howells case 0: 8988c3e34a4SDavid Howells ASSERTCMP(call->state, ==, RXRPC_CALL_DEAD); 8998c3e34a4SDavid Howells break; 9008c3e34a4SDavid Howells case 1: 9018c3e34a4SDavid Howells if (del_timer_sync(&call->deadspan) != 0 && 9028c3e34a4SDavid Howells call->state != RXRPC_CALL_DEAD) 9038c3e34a4SDavid Howells rxrpc_dead_call_expired((unsigned long) call); 9048c3e34a4SDavid Howells if (call->state != RXRPC_CALL_DEAD) 9058c3e34a4SDavid Howells break; 9068c3e34a4SDavid Howells default: 9078c3e34a4SDavid Howells pr_err("Call %p still in use (%d,%d,%s,%lx,%lx)!\n", 9088c3e34a4SDavid Howells call, atomic_read(&call->usage), 9098c3e34a4SDavid Howells atomic_read(&call->ackr_not_idle), 9108c3e34a4SDavid Howells rxrpc_call_states[call->state], 9118c3e34a4SDavid Howells call->flags, call->events); 9128c3e34a4SDavid Howells if (!skb_queue_empty(&call->rx_queue)) 9138c3e34a4SDavid Howells pr_err("Rx queue occupied\n"); 9148c3e34a4SDavid Howells if (!skb_queue_empty(&call->rx_oos_queue)) 9158c3e34a4SDavid Howells pr_err("OOS queue occupied\n"); 9168c3e34a4SDavid Howells break; 9178c3e34a4SDavid Howells } 9188c3e34a4SDavid Howells 9198c3e34a4SDavid Howells write_unlock_bh(&rxrpc_call_lock); 9208c3e34a4SDavid Howells cond_resched(); 9218c3e34a4SDavid Howells write_lock_bh(&rxrpc_call_lock); 9228c3e34a4SDavid Howells } 9238c3e34a4SDavid Howells 9248c3e34a4SDavid Howells write_unlock_bh(&rxrpc_call_lock); 9258c3e34a4SDavid Howells _leave(""); 9268c3e34a4SDavid Howells } 9278c3e34a4SDavid Howells 9288c3e34a4SDavid Howells /* 9298c3e34a4SDavid Howells * handle call lifetime being exceeded 9308c3e34a4SDavid Howells */ 9318c3e34a4SDavid Howells static void rxrpc_call_life_expired(unsigned long _call) 9328c3e34a4SDavid Howells { 9338c3e34a4SDavid Howells struct rxrpc_call *call = (struct rxrpc_call *) _call; 9348c3e34a4SDavid Howells 9358c3e34a4SDavid Howells if (call->state >= RXRPC_CALL_COMPLETE) 9368c3e34a4SDavid Howells return; 9378c3e34a4SDavid Howells 9388c3e34a4SDavid Howells _enter("{%d}", call->debug_id); 9398c3e34a4SDavid Howells read_lock_bh(&call->state_lock); 9408c3e34a4SDavid Howells if (call->state < RXRPC_CALL_COMPLETE) { 9418c3e34a4SDavid Howells set_bit(RXRPC_CALL_EV_LIFE_TIMER, &call->events); 9428c3e34a4SDavid Howells rxrpc_queue_call(call); 9438c3e34a4SDavid Howells } 9448c3e34a4SDavid Howells read_unlock_bh(&call->state_lock); 9458c3e34a4SDavid Howells } 9468c3e34a4SDavid Howells 9478c3e34a4SDavid Howells /* 9488c3e34a4SDavid Howells * handle resend timer expiry 9498c3e34a4SDavid Howells * - may not take call->state_lock as this can deadlock against del_timer_sync() 9508c3e34a4SDavid Howells */ 9518c3e34a4SDavid Howells static void rxrpc_resend_time_expired(unsigned long _call) 9528c3e34a4SDavid Howells { 9538c3e34a4SDavid Howells struct rxrpc_call *call = (struct rxrpc_call *) _call; 9548c3e34a4SDavid Howells 9558c3e34a4SDavid Howells _enter("{%d}", call->debug_id); 9568c3e34a4SDavid Howells 9578c3e34a4SDavid Howells if (call->state >= RXRPC_CALL_COMPLETE) 9588c3e34a4SDavid Howells return; 9598c3e34a4SDavid Howells 9608c3e34a4SDavid Howells clear_bit(RXRPC_CALL_RUN_RTIMER, &call->flags); 9618c3e34a4SDavid Howells if (!test_and_set_bit(RXRPC_CALL_EV_RESEND_TIMER, &call->events)) 9628c3e34a4SDavid Howells rxrpc_queue_call(call); 9638c3e34a4SDavid Howells } 9648c3e34a4SDavid Howells 9658c3e34a4SDavid Howells /* 9668c3e34a4SDavid Howells * handle ACK timer expiry 9678c3e34a4SDavid Howells */ 9688c3e34a4SDavid Howells static void rxrpc_ack_time_expired(unsigned long _call) 9698c3e34a4SDavid Howells { 9708c3e34a4SDavid Howells struct rxrpc_call *call = (struct rxrpc_call *) _call; 9718c3e34a4SDavid Howells 9728c3e34a4SDavid Howells _enter("{%d}", call->debug_id); 9738c3e34a4SDavid Howells 9748c3e34a4SDavid Howells if (call->state >= RXRPC_CALL_COMPLETE) 9758c3e34a4SDavid Howells return; 9768c3e34a4SDavid Howells 9778c3e34a4SDavid Howells read_lock_bh(&call->state_lock); 9788c3e34a4SDavid Howells if (call->state < RXRPC_CALL_COMPLETE && 9798c3e34a4SDavid Howells !test_and_set_bit(RXRPC_CALL_EV_ACK, &call->events)) 9808c3e34a4SDavid Howells rxrpc_queue_call(call); 9818c3e34a4SDavid Howells read_unlock_bh(&call->state_lock); 9828c3e34a4SDavid Howells } 983