rxrpc: Turn connection #defines into enums and put outside struct def
[deliverable/linux.git] / net / rxrpc / conn_client.c
CommitLineData
4a3388c8
DH
1/* Client connection-specific management code.
2 *
3 * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
14#include <linux/slab.h>
15#include <linux/idr.h>
16#include <linux/timer.h>
17#include "ar-internal.h"
18
19/*
20 * We use machine-unique IDs for our client connections.
21 */
22DEFINE_IDR(rxrpc_client_conn_ids);
23static DEFINE_SPINLOCK(rxrpc_conn_id_lock);
24
25/*
26 * Get a connection ID and epoch for a client connection from the global pool.
27 * The connection struct pointer is then recorded in the idr radix tree. The
28 * epoch is changed if this wraps.
29 *
30 * TODO: The IDR tree gets very expensive on memory if the connection IDs are
31 * widely scattered throughout the number space, so we shall need to retire
32 * connections that have, say, an ID more than four times the maximum number of
33 * client conns away from the current allocation point to try and keep the IDs
34 * concentrated. We will also need to retire connections from an old epoch.
35 */
999b69f8 36int rxrpc_get_client_connection_id(struct rxrpc_connection *conn, gfp_t gfp)
4a3388c8
DH
37{
38 u32 epoch;
39 int id;
40
41 _enter("");
42
43 idr_preload(gfp);
4a3388c8
DH
44 spin_lock(&rxrpc_conn_id_lock);
45
46 epoch = rxrpc_epoch;
47
48 /* We could use idr_alloc_cyclic() here, but we really need to know
49 * when the thing wraps so that we can advance the epoch.
50 */
51 if (rxrpc_client_conn_ids.cur == 0)
52 rxrpc_client_conn_ids.cur = 1;
53 id = idr_alloc(&rxrpc_client_conn_ids, conn,
54 rxrpc_client_conn_ids.cur, 0x40000000, GFP_NOWAIT);
55 if (id < 0) {
56 if (id != -ENOSPC)
57 goto error;
58 id = idr_alloc(&rxrpc_client_conn_ids, conn,
59 1, 0x40000000, GFP_NOWAIT);
60 if (id < 0)
61 goto error;
62 epoch++;
63 rxrpc_epoch = epoch;
64 }
65 rxrpc_client_conn_ids.cur = id + 1;
66
67 spin_unlock(&rxrpc_conn_id_lock);
4a3388c8
DH
68 idr_preload_end();
69
70 conn->proto.epoch = epoch;
71 conn->proto.cid = id << RXRPC_CIDSHIFT;
72 set_bit(RXRPC_CONN_HAS_IDR, &conn->flags);
73 _leave(" [CID %x:%x]", epoch, conn->proto.cid);
74 return 0;
75
76error:
77 spin_unlock(&rxrpc_conn_id_lock);
4a3388c8
DH
78 idr_preload_end();
79 _leave(" = %d", id);
80 return id;
81}
82
83/*
84 * Release a connection ID for a client connection from the global pool.
85 */
86void rxrpc_put_client_connection_id(struct rxrpc_connection *conn)
87{
88 if (test_bit(RXRPC_CONN_HAS_IDR, &conn->flags)) {
89 spin_lock(&rxrpc_conn_id_lock);
90 idr_remove(&rxrpc_client_conn_ids,
91 conn->proto.cid >> RXRPC_CIDSHIFT);
92 spin_unlock(&rxrpc_conn_id_lock);
93 }
94}
This page took 0.045211 seconds and 5 git commands to generate.