diff options
author | Alex Elder <elder@dreamhost.com> | 2012-01-23 16:49:27 -0500 |
---|---|---|
committer | Alex Elder <elder@dreamhost.com> | 2012-03-22 11:47:45 -0400 |
commit | f64a93172b97dcfcfa68f595652220653562f605 (patch) | |
tree | 7553ae9e69417d41467431e43b2b8e0d0694ded1 /net | |
parent | a5bc3129a296fd4663c3ef0be5575e82453739dd (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.c | 21 |
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 *); | |||
44 | static void ceph_fault(struct ceph_connection *con); | 44 | static 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) |
51 | static char addr_str[MAX_ADDR_STR][MAX_ADDR_STR_LEN]; | 52 | #define ADDR_STR_COUNT_MASK (ADDR_STR_COUNT - 1) |
52 | static DEFINE_SPINLOCK(addr_str_lock); | 53 | #define MAX_ADDR_STR_LEN 64 /* 54 is enough */ |
53 | static int last_addr_str; | 54 | |
55 | static char addr_str[ADDR_STR_COUNT][MAX_ADDR_STR_LEN]; | ||
56 | static atomic_t addr_str_seq = ATOMIC_INIT(0); | ||
54 | 57 | ||
55 | static struct page *zero_page; /* used in certain error cases */ | 58 | static struct page *zero_page; /* used in certain error cases */ |
56 | static void *zero_page_address; /* kernel virtual addr of zero_page */ | 59 | static 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) { |