aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorAlex Elder <elder@dreamhost.com>2012-01-23 16:49:27 -0500
committerAlex Elder <elder@dreamhost.com>2012-03-22 11:47:45 -0400
commitf64a93172b97dcfcfa68f595652220653562f605 (patch)
tree7553ae9e69417d41467431e43b2b8e0d0694ded1 /net
parenta5bc3129a296fd4663c3ef0be5575e82453739dd (diff)
ceph: kill addr_str_lock spinlock; use atomic instead
A spinlock is used to protect a value used for selecting an array index for a string used for formatting a socket address for human consumption. The index is reset to 0 if it ever reaches the maximum index value. Instead, use an ever-increasing atomic variable as a sequence number, and compute the array index by masking off all but the sequence number's lowest bits. Make the number of entries in the array a power of two to allow the use of such a mask (to avoid jumps in the index value when the sequence number wraps). The length of these strings is somewhat arbitrarily set at 60 bytes. The worst-case length of a string produced is 54 bytes, for an IPv6 address that can't be shortened, e.g.: [1234:5678:9abc:def0:1111:2222:123.234.210.100]:32767 Change it so we arbitrarily use 64 bytes instead; if nothing else it will make the array of these line up better in hex dumps. Rename a few things to reinforce the distinction between the number of strings in the array and the length of individual strings. Signed-off-by: Alex Elder <elder@newdream.net> Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'net')
-rw-r--r--net/ceph/messenger.c21
1 files changed, 10 insertions, 11 deletions
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
index b5536e4e39a1..e86bb3f14859 100644
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -44,13 +44,16 @@ static void con_work(struct work_struct *);
44static void ceph_fault(struct ceph_connection *con); 44static void ceph_fault(struct ceph_connection *con);
45 45
46/* 46/*
47 * nicely render a sockaddr as a string. 47 * Nicely render a sockaddr as a string. An array of formatted
48 * strings is used, to approximate reentrancy.
48 */ 49 */
49#define MAX_ADDR_STR 20 50#define ADDR_STR_COUNT_LOG 5 /* log2(# address strings in array) */
50#define MAX_ADDR_STR_LEN 60 51#define ADDR_STR_COUNT (1 << ADDR_STR_COUNT_LOG)
51static char addr_str[MAX_ADDR_STR][MAX_ADDR_STR_LEN]; 52#define ADDR_STR_COUNT_MASK (ADDR_STR_COUNT - 1)
52static DEFINE_SPINLOCK(addr_str_lock); 53#define MAX_ADDR_STR_LEN 64 /* 54 is enough */
53static int last_addr_str; 54
55static char addr_str[ADDR_STR_COUNT][MAX_ADDR_STR_LEN];
56static atomic_t addr_str_seq = ATOMIC_INIT(0);
54 57
55static struct page *zero_page; /* used in certain error cases */ 58static struct page *zero_page; /* used in certain error cases */
56static void *zero_page_address; /* kernel virtual addr of zero_page */ 59static void *zero_page_address; /* kernel virtual addr of zero_page */
@@ -62,11 +65,7 @@ const char *ceph_pr_addr(const struct sockaddr_storage *ss)
62 struct sockaddr_in *in4 = (void *)ss; 65 struct sockaddr_in *in4 = (void *)ss;
63 struct sockaddr_in6 *in6 = (void *)ss; 66 struct sockaddr_in6 *in6 = (void *)ss;
64 67
65 spin_lock(&addr_str_lock); 68 i = atomic_inc_return(&addr_str_seq) & ADDR_STR_COUNT_MASK;
66 i = last_addr_str++;
67 if (last_addr_str == MAX_ADDR_STR)
68 last_addr_str = 0;
69 spin_unlock(&addr_str_lock);
70 s = addr_str[i]; 69 s = addr_str[i];
71 70
72 switch (ss->ss_family) { 71 switch (ss->ss_family) {