Merge ~racb/ubuntu/+source/memcached:upstream-bump-1.5.6 into ubuntu/+source/memcached:ubuntu/devel
- Git
- lp:~racb/ubuntu/+source/memcached
- upstream-bump-1.5.6
- Merge into ubuntu/devel
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Merge reported by: | Robie Basak | ||||||||
Merged at revision: | 6f2e133e12e997cbdf6d482a8bfa0d35c4932b62 | ||||||||
Proposed branch: | ~racb/ubuntu/+source/memcached:upstream-bump-1.5.6 | ||||||||
Merge into: | ubuntu/+source/memcached:ubuntu/devel | ||||||||
Diff against target: |
1554 lines (+515/-267) 28 files modified
assoc.c (+8/-20) assoc.h (+1/-0) configure (+10/-10) crawler.c (+7/-5) crawler.h (+4/-1) debian/changelog (+10/-0) debian/patches/02_service_wrapper.patch (+6/-8) debian/patches/restore-systemd-sandboxing (+61/-0) debian/patches/series (+1/-1) debian/rules (+2/-0) dev/null (+0/-64) doc/Makefile (+3/-3) items.c (+6/-1) items.h (+1/-0) memcached.c (+28/-9) memcached.spec (+101/-27) memcached_dtrace.d (+2/-6) scripts/memcached-automove-extstore (+25/-30) scripts/memcached.service (+46/-34) scripts/memcached.sysconfig (+10/-0) scripts/memcached@.service (+89/-0) slab_automove_extstore.c (+65/-35) slabs.c (+8/-3) t/issue_67.t (+2/-2) thread.c (+11/-0) timedrun.c (+5/-5) trace.h (+2/-2) version.m4 (+1/-1) |
||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Christian Ehrhardt (community) | Approve | ||
Canonical Server | Pending | ||
Review via email: mp+341340@code.launchpad.net |
Commit message
Description of the change
Christian Ehrhardt (paelzer) wrote : | # |
Christian Ehrhardt (paelzer) wrote : | # |
1. verified the upstream delta between version - ok
Christian Ehrhardt (paelzer) wrote : | # |
2. is it really a bugfix release - ok
https:/
https:/
- UDP - we had disabled that already before, so ok
- ##secure## in service file - handled by you (will check in detail) - ok
Also their git log looks sane.
Christian Ehrhardt (paelzer) wrote : | # |
3. changelog - unsure
That could have followed the usual "merge with X, remaining changes .., Dropped changes",
but it is short and complete
For example we still have:
- debian/NEWS: add explanation and document how to re-enable UDP if necessary.
- rules: Disable tests on armhf, they hang the build.
- added patch to show distribution on version
- Force alignment on in configure.ac
- disable unreliable test.
I think it would be good to have the usual "merge" changelog structure in this case as well.
This is not a hard nack, but I want to hear your opinion on it.
Robie Basak (racb) wrote : | # |
It's not a merge. It's a pure upstream release bump. I haven't pulled in any changes from Debian. So the previous changes from 1.5.4-1 in the changelog are current and read correctly as linear history.
Christian Ehrhardt (paelzer) wrote : | # |
4. checked all new commits - ok
Thanks for the pre-discussion on the sandboxing, certainly better to underatand.
The check seems good if they add more.
If they remove some the patch will not apply.
So in both cases a packager will consciously decide then - that is good.
Robie Basak (racb) wrote : | # |
IOW, it's as if I'm uploading a 1.5.4-1ubuntu4 - but since I also update the upstream version, the package version string becomes 1.5.6-0ubuntu1.
Christian Ehrhardt (paelzer) wrote : | # |
5. Commit structure - ok
I'd have preferred to have
1. Latest Debian
2. Upstream diff
3. old Ubuntu changes as-is
4. new Ubuntu changes by you
But that is a matter of personal taste I assume, fine as it is.
Christian Ehrhardt (paelzer) wrote : | # |
6. Did an upgrade and install from the ppa - all ok
Service still seems started the same way (checked as there were the upstream changes)
Christian Ehrhardt (paelzer) wrote : | # |
7. ran the 11 tests of qa-regression-
One fail, but that it had with the former version as well.
Christian Ehrhardt (paelzer) wrote : | # |
Thanks for the explanations on the changelog structure btw.
Overall this LGTM +1.
Preview Diff
1 | diff --git a/assoc.c b/assoc.c | |||
2 | index 8cdf581..8e7a810 100644 | |||
3 | --- a/assoc.c | |||
4 | +++ b/assoc.c | |||
5 | @@ -27,7 +27,6 @@ | |||
6 | 27 | 27 | ||
7 | 28 | static pthread_cond_t maintenance_cond = PTHREAD_COND_INITIALIZER; | 28 | static pthread_cond_t maintenance_cond = PTHREAD_COND_INITIALIZER; |
8 | 29 | static pthread_mutex_t maintenance_lock = PTHREAD_MUTEX_INITIALIZER; | 29 | static pthread_mutex_t maintenance_lock = PTHREAD_MUTEX_INITIALIZER; |
9 | 30 | static pthread_mutex_t hash_items_counter_lock = PTHREAD_MUTEX_INITIALIZER; | ||
10 | 31 | 30 | ||
11 | 32 | typedef unsigned long int ub4; /* unsigned 4-byte quantities */ | 31 | typedef unsigned long int ub4; /* unsigned 4-byte quantities */ |
12 | 33 | typedef unsigned char ub1; /* unsigned 1-byte quantities */ | 32 | typedef unsigned char ub1; /* unsigned 1-byte quantities */ |
13 | @@ -47,9 +46,6 @@ static item** primary_hashtable = 0; | |||
14 | 47 | */ | 46 | */ |
15 | 48 | static item** old_hashtable = 0; | 47 | static item** old_hashtable = 0; |
16 | 49 | 48 | ||
17 | 50 | /* Number of items in the hash table. */ | ||
18 | 51 | static unsigned int hash_items = 0; | ||
19 | 52 | |||
20 | 53 | /* Flag: Are we in the middle of expanding now? */ | 49 | /* Flag: Are we in the middle of expanding now? */ |
21 | 54 | static bool expanding = false; | 50 | static bool expanding = false; |
22 | 55 | static bool started_expanding = false; | 51 | static bool started_expanding = false; |
23 | @@ -144,12 +140,15 @@ static void assoc_expand(void) { | |||
24 | 144 | } | 140 | } |
25 | 145 | } | 141 | } |
26 | 146 | 142 | ||
28 | 147 | static void assoc_start_expand(void) { | 143 | void assoc_start_expand(uint64_t curr_items) { |
29 | 148 | if (started_expanding) | 144 | if (started_expanding) |
30 | 149 | return; | 145 | return; |
31 | 150 | 146 | ||
34 | 151 | started_expanding = true; | 147 | if (curr_items > (hashsize(hashpower) * 3) / 2 && |
35 | 152 | pthread_cond_signal(&maintenance_cond); | 148 | hashpower < HASHPOWER_MAX) { |
36 | 149 | started_expanding = true; | ||
37 | 150 | pthread_cond_signal(&maintenance_cond); | ||
38 | 151 | } | ||
39 | 153 | } | 152 | } |
40 | 154 | 153 | ||
41 | 155 | /* Note: this isn't an assoc_update. The key must not already exist to call this */ | 154 | /* Note: this isn't an assoc_update. The key must not already exist to call this */ |
42 | @@ -168,15 +167,7 @@ int assoc_insert(item *it, const uint32_t hv) { | |||
43 | 168 | primary_hashtable[hv & hashmask(hashpower)] = it; | 167 | primary_hashtable[hv & hashmask(hashpower)] = it; |
44 | 169 | } | 168 | } |
45 | 170 | 169 | ||
55 | 171 | pthread_mutex_lock(&hash_items_counter_lock); | 170 | MEMCACHED_ASSOC_INSERT(ITEM_key(it), it->nkey); |
47 | 172 | hash_items++; | ||
48 | 173 | if (! expanding && hash_items > (hashsize(hashpower) * 3) / 2 && | ||
49 | 174 | hashpower < HASHPOWER_MAX) { | ||
50 | 175 | assoc_start_expand(); | ||
51 | 176 | } | ||
52 | 177 | pthread_mutex_unlock(&hash_items_counter_lock); | ||
53 | 178 | |||
54 | 179 | MEMCACHED_ASSOC_INSERT(ITEM_key(it), it->nkey, hash_items); | ||
56 | 180 | return 1; | 171 | return 1; |
57 | 181 | } | 172 | } |
58 | 182 | 173 | ||
59 | @@ -185,13 +176,10 @@ void assoc_delete(const char *key, const size_t nkey, const uint32_t hv) { | |||
60 | 185 | 176 | ||
61 | 186 | if (*before) { | 177 | if (*before) { |
62 | 187 | item *nxt; | 178 | item *nxt; |
63 | 188 | pthread_mutex_lock(&hash_items_counter_lock); | ||
64 | 189 | hash_items--; | ||
65 | 190 | pthread_mutex_unlock(&hash_items_counter_lock); | ||
66 | 191 | /* The DTrace probe cannot be triggered as the last instruction | 179 | /* The DTrace probe cannot be triggered as the last instruction |
67 | 192 | * due to possible tail-optimization by the compiler | 180 | * due to possible tail-optimization by the compiler |
68 | 193 | */ | 181 | */ |
70 | 194 | MEMCACHED_ASSOC_DELETE(key, nkey, hash_items); | 182 | MEMCACHED_ASSOC_DELETE(key, nkey); |
71 | 195 | nxt = (*before)->h_next; | 183 | nxt = (*before)->h_next; |
72 | 196 | (*before)->h_next = 0; /* probably pointless, but whatever. */ | 184 | (*before)->h_next = 0; /* probably pointless, but whatever. */ |
73 | 197 | *before = nxt; | 185 | *before = nxt; |
74 | diff --git a/assoc.h b/assoc.h | |||
75 | index dda39a0..fb2c922 100644 | |||
76 | --- a/assoc.h | |||
77 | +++ b/assoc.h | |||
78 | @@ -6,5 +6,6 @@ void assoc_delete(const char *key, const size_t nkey, const uint32_t hv); | |||
79 | 6 | void do_assoc_move_next_bucket(void); | 6 | void do_assoc_move_next_bucket(void); |
80 | 7 | int start_assoc_maintenance_thread(void); | 7 | int start_assoc_maintenance_thread(void); |
81 | 8 | void stop_assoc_maintenance_thread(void); | 8 | void stop_assoc_maintenance_thread(void); |
82 | 9 | void assoc_start_expand(uint64_t curr_items); | ||
83 | 9 | extern unsigned int hashpower; | 10 | extern unsigned int hashpower; |
84 | 10 | extern unsigned int item_lock_hashpower; | 11 | extern unsigned int item_lock_hashpower; |
85 | diff --git a/configure b/configure | |||
86 | index f1e61ff..e479e60 100755 | |||
87 | --- a/configure | |||
88 | +++ b/configure | |||
89 | @@ -1,6 +1,6 @@ | |||
90 | 1 | #! /bin/sh | 1 | #! /bin/sh |
91 | 2 | # Guess values for system-dependent variables and create Makefiles. | 2 | # Guess values for system-dependent variables and create Makefiles. |
93 | 3 | # Generated by GNU Autoconf 2.69 for memcached 1.5.4. | 3 | # Generated by GNU Autoconf 2.69 for memcached 1.5.6. |
94 | 4 | # | 4 | # |
95 | 5 | # Report bugs to <memcached@googlegroups.com>. | 5 | # Report bugs to <memcached@googlegroups.com>. |
96 | 6 | # | 6 | # |
97 | @@ -580,8 +580,8 @@ MAKEFLAGS= | |||
98 | 580 | # Identity of this package. | 580 | # Identity of this package. |
99 | 581 | PACKAGE_NAME='memcached' | 581 | PACKAGE_NAME='memcached' |
100 | 582 | PACKAGE_TARNAME='memcached' | 582 | PACKAGE_TARNAME='memcached' |
103 | 583 | PACKAGE_VERSION='1.5.4' | 583 | PACKAGE_VERSION='1.5.6' |
104 | 584 | PACKAGE_STRING='memcached 1.5.4' | 584 | PACKAGE_STRING='memcached 1.5.6' |
105 | 585 | PACKAGE_BUGREPORT='memcached@googlegroups.com' | 585 | PACKAGE_BUGREPORT='memcached@googlegroups.com' |
106 | 586 | PACKAGE_URL='' | 586 | PACKAGE_URL='' |
107 | 587 | 587 | ||
108 | @@ -1320,7 +1320,7 @@ if test "$ac_init_help" = "long"; then | |||
109 | 1320 | # Omit some internal or obsolete options to make the list less imposing. | 1320 | # Omit some internal or obsolete options to make the list less imposing. |
110 | 1321 | # This message is too long to be a string in the A/UX 3.1 sh. | 1321 | # This message is too long to be a string in the A/UX 3.1 sh. |
111 | 1322 | cat <<_ACEOF | 1322 | cat <<_ACEOF |
113 | 1323 | \`configure' configures memcached 1.5.4 to adapt to many kinds of systems. | 1323 | \`configure' configures memcached 1.5.6 to adapt to many kinds of systems. |
114 | 1324 | 1324 | ||
115 | 1325 | Usage: $0 [OPTION]... [VAR=VALUE]... | 1325 | Usage: $0 [OPTION]... [VAR=VALUE]... |
116 | 1326 | 1326 | ||
117 | @@ -1391,7 +1391,7 @@ fi | |||
118 | 1391 | 1391 | ||
119 | 1392 | if test -n "$ac_init_help"; then | 1392 | if test -n "$ac_init_help"; then |
120 | 1393 | case $ac_init_help in | 1393 | case $ac_init_help in |
122 | 1394 | short | recursive ) echo "Configuration of memcached 1.5.4:";; | 1394 | short | recursive ) echo "Configuration of memcached 1.5.6:";; |
123 | 1395 | esac | 1395 | esac |
124 | 1396 | cat <<\_ACEOF | 1396 | cat <<\_ACEOF |
125 | 1397 | 1397 | ||
126 | @@ -1495,7 +1495,7 @@ fi | |||
127 | 1495 | test -n "$ac_init_help" && exit $ac_status | 1495 | test -n "$ac_init_help" && exit $ac_status |
128 | 1496 | if $ac_init_version; then | 1496 | if $ac_init_version; then |
129 | 1497 | cat <<\_ACEOF | 1497 | cat <<\_ACEOF |
131 | 1498 | memcached configure 1.5.4 | 1498 | memcached configure 1.5.6 |
132 | 1499 | generated by GNU Autoconf 2.69 | 1499 | generated by GNU Autoconf 2.69 |
133 | 1500 | 1500 | ||
134 | 1501 | Copyright (C) 2012 Free Software Foundation, Inc. | 1501 | Copyright (C) 2012 Free Software Foundation, Inc. |
135 | @@ -1964,7 +1964,7 @@ cat >config.log <<_ACEOF | |||
136 | 1964 | This file contains any messages produced by compilers while | 1964 | This file contains any messages produced by compilers while |
137 | 1965 | running configure, to aid debugging if configure makes a mistake. | 1965 | running configure, to aid debugging if configure makes a mistake. |
138 | 1966 | 1966 | ||
140 | 1967 | It was created by memcached $as_me 1.5.4, which was | 1967 | It was created by memcached $as_me 1.5.6, which was |
141 | 1968 | generated by GNU Autoconf 2.69. Invocation command line was | 1968 | generated by GNU Autoconf 2.69. Invocation command line was |
142 | 1969 | 1969 | ||
143 | 1970 | $ $0 $@ | 1970 | $ $0 $@ |
144 | @@ -2899,7 +2899,7 @@ fi | |||
145 | 2899 | 2899 | ||
146 | 2900 | # Define the identity of the package. | 2900 | # Define the identity of the package. |
147 | 2901 | PACKAGE='memcached' | 2901 | PACKAGE='memcached' |
149 | 2902 | VERSION='1.5.4' | 2902 | VERSION='1.5.6' |
150 | 2903 | 2903 | ||
151 | 2904 | 2904 | ||
152 | 2905 | cat >>confdefs.h <<_ACEOF | 2905 | cat >>confdefs.h <<_ACEOF |
153 | @@ -7156,7 +7156,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 | |||
154 | 7156 | # report actual input values of CONFIG_FILES etc. instead of their | 7156 | # report actual input values of CONFIG_FILES etc. instead of their |
155 | 7157 | # values after options handling. | 7157 | # values after options handling. |
156 | 7158 | ac_log=" | 7158 | ac_log=" |
158 | 7159 | This file was extended by memcached $as_me 1.5.4, which was | 7159 | This file was extended by memcached $as_me 1.5.6, which was |
159 | 7160 | generated by GNU Autoconf 2.69. Invocation command line was | 7160 | generated by GNU Autoconf 2.69. Invocation command line was |
160 | 7161 | 7161 | ||
161 | 7162 | CONFIG_FILES = $CONFIG_FILES | 7162 | CONFIG_FILES = $CONFIG_FILES |
162 | @@ -7222,7 +7222,7 @@ _ACEOF | |||
163 | 7222 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 | 7222 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 |
164 | 7223 | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" | 7223 | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" |
165 | 7224 | ac_cs_version="\\ | 7224 | ac_cs_version="\\ |
167 | 7225 | memcached config.status 1.5.4 | 7225 | memcached config.status 1.5.6 |
168 | 7226 | configured by $0, generated by GNU Autoconf 2.69, | 7226 | configured by $0, generated by GNU Autoconf 2.69, |
169 | 7227 | with options \\"\$ac_cs_config\\" | 7227 | with options \\"\$ac_cs_config\\" |
170 | 7228 | 7228 | ||
171 | diff --git a/crawler.c b/crawler.c | |||
172 | index 56e967a..9c81bba 100644 | |||
173 | --- a/crawler.c | |||
174 | +++ b/crawler.c | |||
175 | @@ -252,8 +252,8 @@ static void crawler_metadump_eval(crawler_module_t *cm, item *it, uint32_t hv, i | |||
176 | 252 | int total = snprintf(cm->c.cbuf, 4096, | 252 | int total = snprintf(cm->c.cbuf, 4096, |
177 | 253 | "key=%s exp=%ld la=%llu cas=%llu fetch=%s cls=%u size=%lu\n", | 253 | "key=%s exp=%ld la=%llu cas=%llu fetch=%s cls=%u size=%lu\n", |
178 | 254 | keybuf, | 254 | keybuf, |
181 | 255 | (it->exptime == 0) ? -1 : (long)it->exptime + process_started, | 255 | (it->exptime == 0) ? -1 : (long)(it->exptime + process_started), |
182 | 256 | (unsigned long long)it->time + process_started, | 256 | (unsigned long long)(it->time + process_started), |
183 | 257 | (unsigned long long)ITEM_get_cas(it), | 257 | (unsigned long long)ITEM_get_cas(it), |
184 | 258 | (it->it_flags & ITEM_FETCHED) ? "yes" : "no", | 258 | (it->it_flags & ITEM_FETCHED) ? "yes" : "no", |
185 | 259 | ITEM_clsid(it), | 259 | ITEM_clsid(it), |
186 | @@ -530,6 +530,9 @@ static int do_lru_crawler_start(uint32_t id, uint32_t remaining) { | |||
187 | 530 | crawlers[sid].next = 0; | 530 | crawlers[sid].next = 0; |
188 | 531 | crawlers[sid].prev = 0; | 531 | crawlers[sid].prev = 0; |
189 | 532 | crawlers[sid].time = 0; | 532 | crawlers[sid].time = 0; |
190 | 533 | if (remaining == LRU_CRAWLER_CAP_REMAINING) { | ||
191 | 534 | remaining = do_get_lru_size(sid); | ||
192 | 535 | } | ||
193 | 533 | crawlers[sid].remaining = remaining; | 536 | crawlers[sid].remaining = remaining; |
194 | 534 | crawlers[sid].slabs_clsid = sid; | 537 | crawlers[sid].slabs_clsid = sid; |
195 | 535 | crawlers[sid].reclaimed = 0; | 538 | crawlers[sid].reclaimed = 0; |
196 | @@ -622,7 +625,7 @@ int lru_crawler_start(uint8_t *ids, uint32_t remaining, | |||
197 | 622 | * Also only clear the crawlerstats once per sid. | 625 | * Also only clear the crawlerstats once per sid. |
198 | 623 | */ | 626 | */ |
199 | 624 | enum crawler_result_type lru_crawler_crawl(char *slabs, const enum crawler_run_type type, | 627 | enum crawler_result_type lru_crawler_crawl(char *slabs, const enum crawler_run_type type, |
201 | 625 | void *c, const int sfd) { | 628 | void *c, const int sfd, unsigned int remaining) { |
202 | 626 | char *b = NULL; | 629 | char *b = NULL; |
203 | 627 | uint32_t sid = 0; | 630 | uint32_t sid = 0; |
204 | 628 | int starts = 0; | 631 | int starts = 0; |
205 | @@ -651,8 +654,7 @@ enum crawler_result_type lru_crawler_crawl(char *slabs, const enum crawler_run_t | |||
206 | 651 | } | 654 | } |
207 | 652 | } | 655 | } |
208 | 653 | 656 | ||
211 | 654 | starts = lru_crawler_start(tocrawl, settings.lru_crawler_tocrawl, | 657 | starts = lru_crawler_start(tocrawl, remaining, type, NULL, c, sfd); |
210 | 655 | type, NULL, c, sfd); | ||
212 | 656 | if (starts == -1) { | 658 | if (starts == -1) { |
213 | 657 | return CRAWLER_RUNNING; | 659 | return CRAWLER_RUNNING; |
214 | 658 | } else if (starts == -2) { | 660 | } else if (starts == -2) { |
215 | diff --git a/crawler.h b/crawler.h | |||
216 | index e009548..f7ebba2 100644 | |||
217 | --- a/crawler.h | |||
218 | +++ b/crawler.h | |||
219 | @@ -1,6 +1,8 @@ | |||
220 | 1 | #ifndef CRAWLER_H | 1 | #ifndef CRAWLER_H |
221 | 2 | #define CRAWLER_H | 2 | #define CRAWLER_H |
222 | 3 | 3 | ||
223 | 4 | #define LRU_CRAWLER_CAP_REMAINING -1 | ||
224 | 5 | |||
225 | 4 | typedef struct { | 6 | typedef struct { |
226 | 5 | uint64_t histo[61]; | 7 | uint64_t histo[61]; |
227 | 6 | uint64_t ttl_hourplus; | 8 | uint64_t ttl_hourplus; |
228 | @@ -28,7 +30,8 @@ enum crawler_result_type { | |||
229 | 28 | int start_item_crawler_thread(void); | 30 | int start_item_crawler_thread(void); |
230 | 29 | int stop_item_crawler_thread(void); | 31 | int stop_item_crawler_thread(void); |
231 | 30 | int init_lru_crawler(void *arg); | 32 | int init_lru_crawler(void *arg); |
233 | 31 | enum crawler_result_type lru_crawler_crawl(char *slabs, enum crawler_run_type, void *c, const int sfd); | 33 | enum crawler_result_type lru_crawler_crawl(char *slabs, enum crawler_run_type, |
234 | 34 | void *c, const int sfd, unsigned int remaining); | ||
235 | 32 | int lru_crawler_start(uint8_t *ids, uint32_t remaining, | 35 | int lru_crawler_start(uint8_t *ids, uint32_t remaining, |
236 | 33 | const enum crawler_run_type type, void *data, | 36 | const enum crawler_run_type type, void *data, |
237 | 34 | void *c, const int sfd); | 37 | void *c, const int sfd); |
238 | diff --git a/debian/changelog b/debian/changelog | |||
239 | index 9914ad2..f1ae7d9 100644 | |||
240 | --- a/debian/changelog | |||
241 | +++ b/debian/changelog | |||
242 | @@ -1,3 +1,13 @@ | |||
243 | 1 | memcached (1.5.6-0ubuntu1) bionic; urgency=medium | ||
244 | 2 | |||
245 | 3 | * New upstream bugfix release (LP: #1753839). | ||
246 | 4 | * d/p/disable-udp-by-default.patch: drop (now upstream). | ||
247 | 5 | * d/p/02_service_wrapper.patch: refresh to remove fuzz. | ||
248 | 6 | * d/p/restore-systemd-sandboxing: restore sandboxing in memcached.service | ||
249 | 7 | removed by upstream in 1.5.6 to avoid feature regression (LP: #1755460). | ||
250 | 8 | |||
251 | 9 | -- Robie Basak <robie.basak@ubuntu.com> Tue, 13 Mar 2018 09:59:06 +0000 | ||
252 | 10 | |||
253 | 1 | memcached (1.5.4-1ubuntu3) bionic; urgency=medium | 11 | memcached (1.5.4-1ubuntu3) bionic; urgency=medium |
254 | 2 | 12 | ||
255 | 3 | * SECURITY UPDATE: disable listening on UDP port by default due to | 13 | * SECURITY UPDATE: disable listening on UDP port by default due to |
256 | diff --git a/debian/patches/02_service_wrapper.patch b/debian/patches/02_service_wrapper.patch | |||
257 | index a81bd06..355e194 100644 | |||
258 | --- a/debian/patches/02_service_wrapper.patch | |||
259 | +++ b/debian/patches/02_service_wrapper.patch | |||
260 | @@ -7,10 +7,8 @@ Description: Additions for service unit file | |||
261 | 7 | Last-Update: 2017-09-13 | 7 | Last-Update: 2017-09-13 |
262 | 8 | Forwarded: not-needed | 8 | Forwarded: not-needed |
263 | 9 | 9 | ||
268 | 10 | Index: memcached/scripts/memcached.service | 10 | --- a/scripts/memcached.service |
269 | 11 | =================================================================== | 11 | +++ b/scripts/memcached.service |
266 | 12 | --- memcached.orig/scripts/memcached.service | ||
267 | 13 | +++ memcached/scripts/memcached.service | ||
270 | 14 | @@ -12,10 +12,10 @@ | 12 | @@ -12,10 +12,10 @@ |
271 | 15 | [Unit] | 13 | [Unit] |
272 | 16 | Description=memcached daemon | 14 | Description=memcached daemon |
273 | @@ -22,11 +20,11 @@ Index: memcached/scripts/memcached.service | |||
274 | 22 | -ExecStart=/usr/bin/memcached -p ${PORT} -u ${USER} -m ${CACHESIZE} -c ${MAXCONN} $OPTIONS | 20 | -ExecStart=/usr/bin/memcached -p ${PORT} -u ${USER} -m ${CACHESIZE} -c ${MAXCONN} $OPTIONS |
275 | 23 | +ExecStart=/usr/share/memcached/scripts/systemd-memcached-wrapper /etc/memcached.conf | 21 | +ExecStart=/usr/share/memcached/scripts/systemd-memcached-wrapper /etc/memcached.conf |
276 | 24 | 22 | ||
280 | 25 | # Set up a new file system namespace and mounts private /tmp and /var/tmp directories | 23 | # Set up a new file system namespace and mounts private /tmp and /var/tmp |
281 | 26 | # so this service cannot access the global directories and other processes cannot | 24 | # directories so this service cannot access the global directories and |
282 | 27 | @@ -68,5 +68,10 @@ RestrictAddressFamilies=AF_INET AF_INET6 | 25 | @@ -80,5 +80,10 @@ |
283 | 28 | # Takes away the ability to create or manage any kind of namespace | 26 | # Takes away the ability to create or manage any kind of namespace |
285 | 29 | RestrictNamespaces=true | 27 | ##safer##RestrictNamespaces=true |
286 | 30 | 28 | ||
287 | 31 | +PIDFile=/var/run/memcached/memcached.pid | 29 | +PIDFile=/var/run/memcached/memcached.pid |
288 | 32 | + | 30 | + |
289 | diff --git a/debian/patches/disable-udp-by-default.patch b/debian/patches/disable-udp-by-default.patch | |||
290 | 33 | deleted file mode 100644 | 31 | deleted file mode 100644 |
291 | index 7ca2d13..0000000 | |||
292 | --- a/debian/patches/disable-udp-by-default.patch | |||
293 | +++ /dev/null | |||
294 | @@ -1,64 +0,0 @@ | |||
295 | 1 | From dbb7a8af90054bf4ef51f5814ef7ceb17d83d974 Mon Sep 17 00:00:00 2001 | ||
296 | 2 | From: dormando <dormando@rydia.net> | ||
297 | 3 | Date: Tue, 27 Feb 2018 10:50:45 -0800 | ||
298 | 4 | Subject: [PATCH] disable UDP port by default | ||
299 | 5 | |||
300 | 6 | As reported, UDP amplification attacks have started to use insecure | ||
301 | 7 | internet-exposed memcached instances. UDP used to be a lot more popular as a | ||
302 | 8 | transport for memcached many years ago, but I'm not aware of many recent | ||
303 | 9 | users. | ||
304 | 10 | |||
305 | 11 | Ten years ago, the TCP connection overhead from many clients was relatively | ||
306 | 12 | high (dozens or hundreds per client server), but these days many clients are | ||
307 | 13 | batched, or user fewer processes, or simply anre't worried about it. | ||
308 | 14 | |||
309 | 15 | While changing the default to listen on localhost only would also help, the | ||
310 | 16 | true culprit is UDP. There are many more use cases for using memcached over | ||
311 | 17 | the network than there are for using the UDP protocol. | ||
312 | 18 | --- | ||
313 | 19 | memcached.c | 6 ++---- | ||
314 | 20 | t/issue_67.t | 4 ++-- | ||
315 | 21 | 2 files changed, 4 insertions(+), 6 deletions(-) | ||
316 | 22 | |||
317 | 23 | diff --git a/memcached.c b/memcached.c | ||
318 | 24 | index 88a5f2ebe..7178666e2 100644 | ||
319 | 25 | --- a/memcached.c | ||
320 | 26 | +++ b/memcached.c | ||
321 | 27 | @@ -222,7 +222,7 @@ static void settings_init(void) { | ||
322 | 28 | settings.use_cas = true; | ||
323 | 29 | settings.access = 0700; | ||
324 | 30 | settings.port = 11211; | ||
325 | 31 | - settings.udpport = 11211; | ||
326 | 32 | + settings.udpport = 0; | ||
327 | 33 | /* By default this string should be NULL for getaddrinfo() */ | ||
328 | 34 | settings.inter = NULL; | ||
329 | 35 | settings.maxbytes = 64 * 1024 * 1024; /* default is 64MB */ | ||
330 | 36 | @@ -7479,9 +7479,7 @@ int main (int argc, char **argv) { | ||
331 | 37 | } | ||
332 | 38 | } | ||
333 | 39 | |||
334 | 40 | - if (tcp_specified && settings.port != 0 && !udp_specified) { | ||
335 | 41 | - settings.udpport = settings.port; | ||
336 | 42 | - } else if (udp_specified && settings.udpport != 0 && !tcp_specified) { | ||
337 | 43 | + if (udp_specified && settings.udpport != 0 && !tcp_specified) { | ||
338 | 44 | settings.port = settings.udpport; | ||
339 | 45 | } | ||
340 | 46 | |||
341 | 47 | diff --git a/t/issue_67.t b/t/issue_67.t | ||
342 | 48 | index 69c869f4c..b2d374fa5 100644 | ||
343 | 49 | --- a/t/issue_67.t | ||
344 | 50 | +++ b/t/issue_67.t | ||
345 | 51 | @@ -77,11 +77,11 @@ sub when { | ||
346 | 52 | |||
347 | 53 | # Disabling the defaults since it conflicts with a running instance. | ||
348 | 54 | # when('no arguments', '', 11211, 11211); | ||
349 | 55 | -when('specifying tcp port', '-p 11212', 11212, 11212); | ||
350 | 56 | +when('specifying tcp port', '-p 11212', 11212, -1); | ||
351 | 57 | when('specifying udp port', '-U 11222', 11222, 11222); | ||
352 | 58 | when('specifying tcp ephemeral port', '-p -1', 0, 0); | ||
353 | 59 | when('specifying udp ephemeral port', '-U -1', 0, 0); | ||
354 | 60 | -when('tcp port disabled', '-p 0', -1, 11211); | ||
355 | 61 | +when('tcp port disabled', '-p 0', -1, -1); | ||
356 | 62 | when('udp port disabled', '-U 0', 11211, -1); | ||
357 | 63 | when('specifying tcp and udp ports', '-p 11232 -U 11233', 11232, 11233); | ||
358 | 64 | when('specifying tcp and disabling udp', '-p 11242 -U 0', 11242, -1); | ||
359 | diff --git a/debian/patches/restore-systemd-sandboxing b/debian/patches/restore-systemd-sandboxing | |||
360 | 65 | new file mode 100644 | 0 | new file mode 100644 |
361 | index 0000000..584e774 | |||
362 | --- /dev/null | |||
363 | +++ b/debian/patches/restore-systemd-sandboxing | |||
364 | @@ -0,0 +1,61 @@ | |||
365 | 1 | Author: Robie Basak <robie.basak@canonical.com> | ||
366 | 2 | Description: Restore systemd sandboxing | ||
367 | 3 | Upstream regressed systemd sandboxing for everyone by default because RHEL | ||
368 | 4 | cannot support it. Put it back again to avoid this functional regression. | ||
369 | 5 | Bug: https://github.com/memcached/memcached/issues/359 | ||
370 | 6 | Bug-Ubuntu: https://bugs.launchpad.net/memcached/+bug/1755460 | ||
371 | 7 | Forwarded: not-needed | ||
372 | 8 | Last-Update: 2018-03-13 | ||
373 | 9 | |||
374 | 10 | --- a/scripts/memcached.service | ||
375 | 11 | +++ b/scripts/memcached.service | ||
376 | 12 | @@ -42,21 +42,16 @@ | ||
377 | 13 | # of this unit. Protects against vulnerabilities such as CVE-2016-8655 | ||
378 | 14 | RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX | ||
379 | 15 | |||
380 | 16 | - | ||
381 | 17 | -# Some security features are not in the older versions of systemd used by | ||
382 | 18 | -# e.g. RHEL7/CentOS 7. The below settings are automatically edited at package | ||
383 | 19 | -# build time to uncomment them if the target platform supports them. | ||
384 | 20 | - | ||
385 | 21 | # Attempts to create memory mappings that are writable and executable at | ||
386 | 22 | # the same time, or to change existing memory mappings to become executable | ||
387 | 23 | # are prohibited. | ||
388 | 24 | -##safer##MemoryDenyWriteExecute=true | ||
389 | 25 | +MemoryDenyWriteExecute=true | ||
390 | 26 | |||
391 | 27 | # Explicit module loading will be denied. This allows to turn off module | ||
392 | 28 | # load and unload operations on modular kernels. It is recommended to turn | ||
393 | 29 | # this on for most services that do not need special file systems or extra | ||
394 | 30 | # kernel modules to work. | ||
395 | 31 | -##safer##ProtectKernelModules=true | ||
396 | 32 | +ProtectKernelModules=true | ||
397 | 33 | |||
398 | 34 | # Kernel variables accessible through /proc/sys, /sys, /proc/sysrq-trigger, | ||
399 | 35 | # /proc/latency_stats, /proc/acpi, /proc/timer_stats, /proc/fs and /proc/irq | ||
400 | 36 | @@ -64,21 +59,21 @@ | ||
401 | 37 | # kernel variables should only be written at boot-time, with the sysctl.d(5) | ||
402 | 38 | # mechanism. Almost no services need to write to these at runtime; it is hence | ||
403 | 39 | # recommended to turn this on for most services. | ||
404 | 40 | -##safer##ProtectKernelTunables=true | ||
405 | 41 | +ProtectKernelTunables=true | ||
406 | 42 | |||
407 | 43 | # The Linux Control Groups (cgroups(7)) hierarchies accessible through | ||
408 | 44 | # /sys/fs/cgroup will be made read-only to all processes of the unit. | ||
409 | 45 | # Except for container managers no services should require write access | ||
410 | 46 | # to the control groups hierarchies; it is hence recommended to turn this | ||
411 | 47 | # on for most services | ||
412 | 48 | -##safer##ProtectControlGroups=true | ||
413 | 49 | +ProtectControlGroups=true | ||
414 | 50 | |||
415 | 51 | # Any attempts to enable realtime scheduling in a process of the unit are | ||
416 | 52 | # refused. | ||
417 | 53 | -##safer##RestrictRealtime=true | ||
418 | 54 | +RestrictRealtime=true | ||
419 | 55 | |||
420 | 56 | # Takes away the ability to create or manage any kind of namespace | ||
421 | 57 | -##safer##RestrictNamespaces=true | ||
422 | 58 | +RestrictNamespaces=true | ||
423 | 59 | |||
424 | 60 | PIDFile=/var/run/memcached/memcached.pid | ||
425 | 61 | |||
426 | diff --git a/debian/patches/series b/debian/patches/series | |||
427 | index 4e08bec..bb9c45b 100644 | |||
428 | --- a/debian/patches/series | |||
429 | +++ b/debian/patches/series | |||
430 | @@ -5,4 +5,4 @@ | |||
431 | 5 | fix-distribution.patch | 5 | fix-distribution.patch |
432 | 6 | always_enable_alignment.patch | 6 | always_enable_alignment.patch |
433 | 7 | disable_watcher_test.patch | 7 | disable_watcher_test.patch |
435 | 8 | disable-udp-by-default.patch | 8 | restore-systemd-sandboxing |
436 | diff --git a/debian/rules b/debian/rules | |||
437 | index ccd01ec..9fc8d04 100755 | |||
438 | --- a/debian/rules | |||
439 | +++ b/debian/rules | |||
440 | @@ -26,6 +26,8 @@ override_dh_auto_install: | |||
441 | 26 | $(CURDIR)/debian/memcached.init | 26 | $(CURDIR)/debian/memcached.init |
442 | 27 | install -m 755 $(CURDIR)/scripts/memcached.service \ | 27 | install -m 755 $(CURDIR)/scripts/memcached.service \ |
443 | 28 | $(CURDIR)/debian/memcached.service | 28 | $(CURDIR)/debian/memcached.service |
444 | 29 | # Check for LP: #1755460 | ||
445 | 30 | if grep -i '##safer##' $(CURDIR)/debian/memcached.service >/dev/null 2>&1; then echo "ERROR: debian/patches/restore-systemd-sandboxing is incomplete; please see LP: #1755460" >&2; exit 1; fi | ||
446 | 29 | install -m 755 $(CURDIR)/scripts/damemtop $(SCRIPTS) | 31 | install -m 755 $(CURDIR)/scripts/damemtop $(SCRIPTS) |
447 | 30 | install -m 644 $(CURDIR)/scripts/damemtop.yaml $(SCRIPTS) | 32 | install -m 644 $(CURDIR)/scripts/damemtop.yaml $(SCRIPTS) |
448 | 31 | install -m 644 $(CURDIR)/scripts/README.damemtop $(SCRIPTS) | 33 | install -m 644 $(CURDIR)/scripts/README.damemtop $(SCRIPTS) |
449 | diff --git a/doc/Makefile b/doc/Makefile | |||
450 | index 881c525..0337680 100644 | |||
451 | --- a/doc/Makefile | |||
452 | +++ b/doc/Makefile | |||
453 | @@ -191,10 +191,10 @@ OBJEXT = o | |||
454 | 191 | PACKAGE = memcached | 191 | PACKAGE = memcached |
455 | 192 | PACKAGE_BUGREPORT = memcached@googlegroups.com | 192 | PACKAGE_BUGREPORT = memcached@googlegroups.com |
456 | 193 | PACKAGE_NAME = memcached | 193 | PACKAGE_NAME = memcached |
458 | 194 | PACKAGE_STRING = memcached 1.5.4 | 194 | PACKAGE_STRING = memcached 1.5.6 |
459 | 195 | PACKAGE_TARNAME = memcached | 195 | PACKAGE_TARNAME = memcached |
460 | 196 | PACKAGE_URL = | 196 | PACKAGE_URL = |
462 | 197 | PACKAGE_VERSION = 1.5.4 | 197 | PACKAGE_VERSION = 1.5.6 |
463 | 198 | PATH_SEPARATOR = : | 198 | PATH_SEPARATOR = : |
464 | 199 | PROFILER = /usr/bin/gcov | 199 | PROFILER = /usr/bin/gcov |
465 | 200 | PROFILER_FLAGS = -fprofile-arcs -ftest-coverage | 200 | PROFILER_FLAGS = -fprofile-arcs -ftest-coverage |
466 | @@ -202,7 +202,7 @@ PROFILER_LDFLAGS = -lgcov | |||
467 | 202 | SET_MAKE = | 202 | SET_MAKE = |
468 | 203 | SHELL = /bin/bash | 203 | SHELL = /bin/bash |
469 | 204 | STRIP = | 204 | STRIP = |
471 | 205 | VERSION = 1.5.4 | 205 | VERSION = 1.5.6 |
472 | 206 | XML2RFC = /usr/bin/xml2rfc | 206 | XML2RFC = /usr/bin/xml2rfc |
473 | 207 | XSLTPROC = no | 207 | XSLTPROC = no |
474 | 208 | abs_builddir = /home/dormando/d/p/danga/git/memcached/doc | 208 | abs_builddir = /home/dormando/d/p/danga/git/memcached/doc |
475 | diff --git a/items.c b/items.c | |||
476 | index 400048b..0aefaf0 100644 | |||
477 | --- a/items.c | |||
478 | +++ b/items.c | |||
479 | @@ -138,6 +138,11 @@ static unsigned int temp_lru_size(int slabs_clsid) { | |||
480 | 138 | return ret; | 138 | return ret; |
481 | 139 | } | 139 | } |
482 | 140 | 140 | ||
483 | 141 | /* must be locked before call */ | ||
484 | 142 | unsigned int do_get_lru_size(uint32_t id) { | ||
485 | 143 | return sizes[id]; | ||
486 | 144 | } | ||
487 | 145 | |||
488 | 141 | /* Enable this for reference-count debugging. */ | 146 | /* Enable this for reference-count debugging. */ |
489 | 142 | #if 0 | 147 | #if 0 |
490 | 143 | # define DEBUG_REFCNT(it,op) \ | 148 | # define DEBUG_REFCNT(it,op) \ |
491 | @@ -925,7 +930,7 @@ void item_stats_sizes(ADD_STAT add_stats, void *c) { | |||
492 | 925 | int i; | 930 | int i; |
493 | 926 | for (i = 0; i < stats_sizes_buckets; i++) { | 931 | for (i = 0; i < stats_sizes_buckets; i++) { |
494 | 927 | if (stats_sizes_hist[i] != 0) { | 932 | if (stats_sizes_hist[i] != 0) { |
496 | 928 | char key[8]; | 933 | char key[12]; |
497 | 929 | snprintf(key, sizeof(key), "%d", i * 32); | 934 | snprintf(key, sizeof(key), "%d", i * 32); |
498 | 930 | APPEND_STAT(key, "%u", stats_sizes_hist[i]); | 935 | APPEND_STAT(key, "%u", stats_sizes_hist[i]); |
499 | 931 | } | 936 | } |
500 | diff --git a/items.h b/items.h | |||
501 | index bf126d7..3b99c66 100644 | |||
502 | --- a/items.h | |||
503 | +++ b/items.h | |||
504 | @@ -25,6 +25,7 @@ void do_item_update_nolock(item *it); | |||
505 | 25 | int do_item_replace(item *it, item *new_it, const uint32_t hv); | 25 | int do_item_replace(item *it, item *new_it, const uint32_t hv); |
506 | 26 | 26 | ||
507 | 27 | int item_is_flushed(item *it); | 27 | int item_is_flushed(item *it); |
508 | 28 | unsigned int do_get_lru_size(uint32_t id); | ||
509 | 28 | 29 | ||
510 | 29 | void do_item_linktail_q(item *it); | 30 | void do_item_linktail_q(item *it); |
511 | 30 | void do_item_unlinktail_q(item *it); | 31 | void do_item_unlinktail_q(item *it); |
512 | diff --git a/memcached.c b/memcached.c | |||
513 | index a8a724c..7178666 100644 | |||
514 | --- a/memcached.c | |||
515 | +++ b/memcached.c | |||
516 | @@ -222,7 +222,7 @@ static void settings_init(void) { | |||
517 | 222 | settings.use_cas = true; | 222 | settings.use_cas = true; |
518 | 223 | settings.access = 0700; | 223 | settings.access = 0700; |
519 | 224 | settings.port = 11211; | 224 | settings.port = 11211; |
521 | 225 | settings.udpport = 11211; | 225 | settings.udpport = 0; |
522 | 226 | /* By default this string should be NULL for getaddrinfo() */ | 226 | /* By default this string should be NULL for getaddrinfo() */ |
523 | 227 | settings.inter = NULL; | 227 | settings.inter = NULL; |
524 | 228 | settings.maxbytes = 64 * 1024 * 1024; /* default is 64MB */ | 228 | settings.maxbytes = 64 * 1024 * 1024; /* default is 64MB */ |
525 | @@ -3338,7 +3338,7 @@ static void process_stats_conns(ADD_STAT add_stats, void *c) { | |||
526 | 3338 | int i; | 3338 | int i; |
527 | 3339 | char key_str[STAT_KEY_LEN]; | 3339 | char key_str[STAT_KEY_LEN]; |
528 | 3340 | char val_str[STAT_VAL_LEN]; | 3340 | char val_str[STAT_VAL_LEN]; |
530 | 3341 | char conn_name[MAXPATHLEN + sizeof("unix:")]; | 3341 | char conn_name[MAXPATHLEN + sizeof("unix:") + sizeof("65535")]; |
531 | 3342 | int klen = 0, vlen = 0; | 3342 | int klen = 0, vlen = 0; |
532 | 3343 | 3343 | ||
533 | 3344 | assert(add_stats); | 3344 | assert(add_stats); |
534 | @@ -4525,7 +4525,7 @@ static void process_lru_command(conn *c, token_t *tokens, const size_t ntokens) | |||
535 | 4525 | static void process_extstore_command(conn *c, token_t *tokens, const size_t ntokens) { | 4525 | static void process_extstore_command(conn *c, token_t *tokens, const size_t ntokens) { |
536 | 4526 | set_noreply_maybe(c, tokens, ntokens); | 4526 | set_noreply_maybe(c, tokens, ntokens); |
537 | 4527 | bool ok = true; | 4527 | bool ok = true; |
539 | 4528 | if (ntokens < 3) { | 4528 | if (ntokens < 4) { |
540 | 4529 | ok = false; | 4529 | ok = false; |
541 | 4530 | } else if (strcmp(tokens[1].value, "free_memchunks") == 0 && ntokens > 4) { | 4530 | } else if (strcmp(tokens[1].value, "free_memchunks") == 0 && ntokens > 4) { |
542 | 4531 | /* per-slab-class free chunk setting. */ | 4531 | /* per-slab-class free chunk setting. */ |
543 | @@ -4770,7 +4770,8 @@ static void process_command(conn *c, char *command) { | |||
544 | 4770 | return; | 4770 | return; |
545 | 4771 | } | 4771 | } |
546 | 4772 | 4772 | ||
548 | 4773 | rv = lru_crawler_crawl(tokens[2].value, CRAWLER_EXPIRED, NULL, 0); | 4773 | rv = lru_crawler_crawl(tokens[2].value, CRAWLER_EXPIRED, NULL, 0, |
549 | 4774 | settings.lru_crawler_tocrawl); | ||
550 | 4774 | switch(rv) { | 4775 | switch(rv) { |
551 | 4775 | case CRAWLER_OK: | 4776 | case CRAWLER_OK: |
552 | 4776 | out_string(c, "OK"); | 4777 | out_string(c, "OK"); |
553 | @@ -4800,7 +4801,7 @@ static void process_command(conn *c, char *command) { | |||
554 | 4800 | } | 4801 | } |
555 | 4801 | 4802 | ||
556 | 4802 | int rv = lru_crawler_crawl(tokens[2].value, CRAWLER_METADUMP, | 4803 | int rv = lru_crawler_crawl(tokens[2].value, CRAWLER_METADUMP, |
558 | 4803 | c, c->sfd); | 4804 | c, c->sfd, LRU_CRAWLER_CAP_REMAINING); |
559 | 4804 | switch(rv) { | 4805 | switch(rv) { |
560 | 4805 | case CRAWLER_OK: | 4806 | case CRAWLER_OK: |
561 | 4806 | out_string(c, "OK"); | 4807 | out_string(c, "OK"); |
562 | @@ -5973,6 +5974,7 @@ static int server_sockets(int port, enum network_transport transport, | |||
563 | 5973 | char *e = strchr(p, ']'); | 5974 | char *e = strchr(p, ']'); |
564 | 5974 | if (e == NULL) { | 5975 | if (e == NULL) { |
565 | 5975 | fprintf(stderr, "Invalid IPV6 address: \"%s\"", p); | 5976 | fprintf(stderr, "Invalid IPV6 address: \"%s\"", p); |
566 | 5977 | free(list); | ||
567 | 5976 | return 1; | 5978 | return 1; |
568 | 5977 | } | 5979 | } |
569 | 5978 | h = ++p; // skip the opening '[' | 5980 | h = ++p; // skip the opening '[' |
570 | @@ -5991,6 +5993,7 @@ static int server_sockets(int port, enum network_transport transport, | |||
571 | 5991 | ++s; | 5993 | ++s; |
572 | 5992 | if (!safe_strtol(s, &the_port)) { | 5994 | if (!safe_strtol(s, &the_port)) { |
573 | 5993 | fprintf(stderr, "Invalid port number: \"%s\"", s); | 5995 | fprintf(stderr, "Invalid port number: \"%s\"", s); |
574 | 5996 | free(list); | ||
575 | 5994 | return 1; | 5997 | return 1; |
576 | 5995 | } | 5998 | } |
577 | 5996 | } | 5999 | } |
578 | @@ -6126,6 +6129,10 @@ static void clock_handler(const int fd, const short which, void *arg) { | |||
579 | 6126 | #endif | 6129 | #endif |
580 | 6127 | } | 6130 | } |
581 | 6128 | 6131 | ||
582 | 6132 | // While we're here, check for hash table expansion. | ||
583 | 6133 | // This function should be quick to avoid delaying the timer. | ||
584 | 6134 | assoc_start_expand(stats_state.curr_items); | ||
585 | 6135 | |||
586 | 6129 | evtimer_set(&clockevent, clock_handler, 0); | 6136 | evtimer_set(&clockevent, clock_handler, 0); |
587 | 6130 | event_base_set(main_base, &clockevent); | 6137 | event_base_set(main_base, &clockevent); |
588 | 6131 | evtimer_add(&clockevent, &t); | 6138 | evtimer_add(&clockevent, &t); |
589 | @@ -7472,9 +7479,7 @@ int main (int argc, char **argv) { | |||
590 | 7472 | } | 7479 | } |
591 | 7473 | } | 7480 | } |
592 | 7474 | 7481 | ||
596 | 7475 | if (tcp_specified && settings.port != 0 && !udp_specified) { | 7482 | if (udp_specified && settings.udpport != 0 && !tcp_specified) { |
594 | 7476 | settings.udpport = settings.port; | ||
595 | 7477 | } else if (udp_specified && settings.udpport != 0 && !tcp_specified) { | ||
597 | 7478 | settings.port = settings.udpport; | 7483 | settings.port = settings.udpport; |
598 | 7479 | } | 7484 | } |
599 | 7480 | 7485 | ||
600 | @@ -7568,7 +7573,17 @@ int main (int argc, char **argv) { | |||
601 | 7568 | } | 7573 | } |
602 | 7569 | 7574 | ||
603 | 7570 | /* initialize main thread libevent instance */ | 7575 | /* initialize main thread libevent instance */ |
604 | 7576 | #if defined(LIBEVENT_VERSION_NUMBER) && LIBEVENT_VERSION_NUMBER >= 0x02000101 | ||
605 | 7577 | /* If libevent version is larger/equal to 2.0.2-alpha, use newer version */ | ||
606 | 7578 | struct event_config *ev_config; | ||
607 | 7579 | ev_config = event_config_new(); | ||
608 | 7580 | event_config_set_flag(ev_config, EVENT_BASE_FLAG_NOLOCK); | ||
609 | 7581 | main_base = event_base_new_with_config(ev_config); | ||
610 | 7582 | event_config_free(ev_config); | ||
611 | 7583 | #else | ||
612 | 7584 | /* Otherwise, use older API */ | ||
613 | 7571 | main_base = event_init(); | 7585 | main_base = event_init(); |
614 | 7586 | #endif | ||
615 | 7572 | 7587 | ||
616 | 7573 | /* initialize other stuff */ | 7588 | /* initialize other stuff */ |
617 | 7574 | logger_init(); | 7589 | logger_init(); |
618 | @@ -7710,8 +7725,9 @@ int main (int argc, char **argv) { | |||
619 | 7710 | if (portnumber_file) { | 7725 | if (portnumber_file) { |
620 | 7711 | fclose(portnumber_file); | 7726 | fclose(portnumber_file); |
621 | 7712 | rename(temp_portnumber_filename, portnumber_filename); | 7727 | rename(temp_portnumber_filename, portnumber_filename); |
622 | 7713 | free(temp_portnumber_filename); | ||
623 | 7714 | } | 7728 | } |
624 | 7729 | if (temp_portnumber_filename) | ||
625 | 7730 | free(temp_portnumber_filename); | ||
626 | 7715 | } | 7731 | } |
627 | 7716 | 7732 | ||
628 | 7717 | /* Give the sockets a moment to open. I know this is dumb, but the error | 7733 | /* Give the sockets a moment to open. I know this is dumb, but the error |
629 | @@ -7753,5 +7769,8 @@ int main (int argc, char **argv) { | |||
630 | 7753 | if (u_socket) | 7769 | if (u_socket) |
631 | 7754 | free(u_socket); | 7770 | free(u_socket); |
632 | 7755 | 7771 | ||
633 | 7772 | /* cleanup base */ | ||
634 | 7773 | event_base_free(main_base); | ||
635 | 7774 | |||
636 | 7756 | return retval; | 7775 | return retval; |
637 | 7757 | } | 7776 | } |
638 | diff --git a/memcached.spec b/memcached.spec | |||
639 | index a149db3..697c38f 100644 | |||
640 | --- a/memcached.spec | |||
641 | +++ b/memcached.spec | |||
642 | @@ -1,21 +1,48 @@ | |||
643 | 1 | # Set with_systemd on distros that use it, so we can install the service | ||
644 | 2 | # file, otherwise the sysvinit script will be installed | ||
645 | 3 | %if 0%{?fedora} >= 14 || 0%{?rhel} >= 7 || 0%{?suse_version} >= 1210 | ||
646 | 4 | %global with_systemd 1 | ||
647 | 5 | BuildRequires: systemd-units | ||
648 | 6 | |||
649 | 7 | # Disable some systemd safety features on OSes without a new enough systemd | ||
650 | 8 | # (new enough is systemd >= 233) | ||
651 | 9 | %if 0%{?fedora} < 26 || 0%{?rhel} > 0 | ||
652 | 10 | %global safer_systemd 0 | ||
653 | 11 | %else | ||
654 | 12 | %global safer_systemd 1 | ||
655 | 13 | %endif | ||
656 | 14 | |||
657 | 15 | %else | ||
658 | 16 | %global with_systemd 0 | ||
659 | 17 | %endif | ||
660 | 18 | |||
661 | 1 | Name: memcached | 19 | Name: memcached |
663 | 2 | Version: 1.5.4 | 20 | Version: 1.5.6 |
664 | 3 | Release: 1%{?dist} | 21 | Release: 1%{?dist} |
665 | 4 | Summary: High Performance, Distributed Memory Object Cache | 22 | Summary: High Performance, Distributed Memory Object Cache |
666 | 5 | 23 | ||
667 | 6 | Group: System Environment/Daemons | 24 | Group: System Environment/Daemons |
668 | 7 | License: BSD | 25 | License: BSD |
669 | 8 | URL: http://memcached.org | 26 | URL: http://memcached.org |
671 | 9 | Source0: http://memcached.org/files/%{name}-1.5.4.tar.gz | 27 | Source0: http://memcached.org/files/%{name}-%{version}.tar.gz |
672 | 28 | Source1: memcached.sysconfig | ||
673 | 29 | Source2: memcached.service | ||
674 | 30 | Source3: memcached@.service | ||
675 | 10 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) | 31 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) |
676 | 11 | 32 | ||
677 | 12 | BuildRequires: libevent-devel | 33 | BuildRequires: libevent-devel |
678 | 13 | BuildRequires: perl(Test::More) | 34 | BuildRequires: perl(Test::More) |
679 | 14 | BuildRequires: /usr/bin/prove | 35 | BuildRequires: /usr/bin/prove |
680 | 15 | Requires: initscripts | 36 | Requires: initscripts |
681 | 37 | %if %{with_systemd} | ||
682 | 38 | Requires(post): systemd-units | ||
683 | 39 | Requires(preun): systemd-units | ||
684 | 40 | Requires(postun): systemd-units | ||
685 | 41 | %else | ||
686 | 16 | Requires(post): /sbin/chkconfig | 42 | Requires(post): /sbin/chkconfig |
687 | 17 | Requires(preun): /sbin/chkconfig, /sbin/service | 43 | Requires(preun): /sbin/chkconfig, /sbin/service |
688 | 18 | Requires(postun): /sbin/service | 44 | Requires(postun): /sbin/service |
689 | 45 | %endif | ||
690 | 19 | 46 | ||
691 | 20 | %description | 47 | %description |
692 | 21 | memcached is a high-performance, distributed memory object caching | 48 | memcached is a high-performance, distributed memory object caching |
693 | @@ -23,7 +50,7 @@ system, generic in nature, but intended for use in speeding up dynamic | |||
694 | 23 | web applications by alleviating database load. | 50 | web applications by alleviating database load. |
695 | 24 | 51 | ||
696 | 25 | %prep | 52 | %prep |
698 | 26 | %setup -q -n %{name}-1.5.4 | 53 | %setup -q -n %{name}-%{version} |
699 | 27 | 54 | ||
700 | 28 | 55 | ||
701 | 29 | %build | 56 | %build |
702 | @@ -31,53 +58,90 @@ web applications by alleviating database load. | |||
703 | 31 | 58 | ||
704 | 32 | make %{?_smp_mflags} | 59 | make %{?_smp_mflags} |
705 | 33 | 60 | ||
706 | 61 | |||
707 | 34 | %check | 62 | %check |
708 | 35 | make test | 63 | make test |
709 | 36 | 64 | ||
710 | 65 | |||
711 | 37 | %install | 66 | %install |
712 | 38 | rm -rf %{buildroot} | 67 | rm -rf %{buildroot} |
713 | 39 | make install DESTDIR=%{buildroot} | 68 | make install DESTDIR=%{buildroot} |
714 | 40 | 69 | ||
715 | 41 | # remove memcached-debug | 70 | # remove memcached-debug |
717 | 42 | rm -f %{buildroot}/%{_bindir}/memcached-debug | 71 | rm -f %{buildroot}/%{_bindir}/%{name}-debug |
718 | 43 | 72 | ||
719 | 44 | # Perl script for monitoring memcached | 73 | # Perl script for monitoring memcached |
721 | 45 | install -Dp -m0755 scripts/memcached-tool %{buildroot}%{_bindir}/memcached-tool | 74 | install -Dp -m0755 scripts/memcached-tool %{buildroot}%{_bindir}/%{name}-tool |
722 | 46 | 75 | ||
723 | 47 | # Init script | 76 | # Init script |
725 | 48 | install -Dp -m0755 scripts/memcached.sysv %{buildroot}%{_initrddir}/memcached | 77 | %if %{with_systemd} |
726 | 78 | install -Dp -m0755 scripts/memcached.service %{buildroot}%{_unitdir}/%{name}.service | ||
727 | 79 | install -Dp -m0755 scripts/memcached@.service %{buildroot}%{_unitdir}/%{name}@.service | ||
728 | 80 | |||
729 | 81 | if [ %{safer_systemd} -gt 0 ]; then | ||
730 | 82 | sed -e -i 's/^##safer##//g' %{buildroot}%{_unitdir}/%{name}.service %{buildroot}%{_unitdir}/%{name}@.service | ||
731 | 83 | else | ||
732 | 84 | sed -e -i 's/^##safer##/#/g' %{buildroot}%{_unitdir}/%{name}.service %{buildroot}%{_unitdir}/%{name}@.service | ||
733 | 85 | fi | ||
734 | 86 | %else | ||
735 | 87 | install -Dp -m0755 scripts/memcached.sysv %{buildroot}%{_initrddir}/%{name} | ||
736 | 88 | %endif | ||
737 | 49 | 89 | ||
738 | 50 | # Default configs | 90 | # Default configs |
747 | 51 | mkdir -p %{buildroot}/%{_sysconfdir}/sysconfig | 91 | install -Dp -m0644 scripts/memcached.sysconfig %{buildroot}%{_sysconfdir}/sysconfig/%{name} |
740 | 52 | cat <<EOF >%{buildroot}/%{_sysconfdir}/sysconfig/%{name} | ||
741 | 53 | PORT="11211" | ||
742 | 54 | USER="nobody" | ||
743 | 55 | MAXCONN="1024" | ||
744 | 56 | CACHESIZE="64" | ||
745 | 57 | OPTIONS="" | ||
746 | 58 | EOF | ||
748 | 59 | 92 | ||
749 | 60 | # pid directory | 93 | # pid directory |
751 | 61 | mkdir -p %{buildroot}/%{_localstatedir}/run/memcached | 94 | mkdir -p %{buildroot}/%{_localstatedir}/run/%{name} |
752 | 95 | |||
753 | 62 | 96 | ||
754 | 63 | %clean | 97 | %clean |
755 | 64 | rm -rf %{buildroot} | 98 | rm -rf %{buildroot} |
756 | 65 | 99 | ||
757 | 66 | 100 | ||
758 | 67 | %post | 101 | %post |
760 | 68 | /sbin/chkconfig --add %{name} | 102 | if [ $1 -eq 1 ]; then |
761 | 103 | # Initial install | ||
762 | 104 | %if %{with_systemd} | ||
763 | 105 | /bin/systemctl daemon-reload >/dev/null 2>&1 || : | ||
764 | 106 | %else | ||
765 | 107 | /sbin/chkconfig --add %{name} | ||
766 | 108 | %endif | ||
767 | 109 | fi | ||
768 | 110 | |||
769 | 69 | 111 | ||
770 | 70 | %preun | 112 | %preun |
771 | 71 | if [ "$1" = 0 ] ; then | 113 | if [ "$1" = 0 ] ; then |
773 | 72 | /sbin/service %{name} stop > /dev/null 2>&1 | 114 | # Removal, not upgrade |
774 | 115 | %if %{with_systemd} | ||
775 | 116 | /bin/systemctl --no-reload disable %{name}.service > /dev/null 2>&1 || : | ||
776 | 117 | /bin/systemctl --no-reload disable %{name}@\*.service > /dev/null 2>&1 || : | ||
777 | 118 | /bin/systemctl stop %{name}.service > /dev/null 2>&1 || : | ||
778 | 119 | /bin/systemctl stop %{name}@\*.service > /dev/null 2>&1 || : | ||
779 | 120 | %else | ||
780 | 121 | /sbin/service %{name} stop > /dev/null 2&>1 || : | ||
781 | 73 | /sbin/chkconfig --del %{name} | 122 | /sbin/chkconfig --del %{name} |
782 | 123 | %endif | ||
783 | 74 | fi | 124 | fi |
784 | 125 | |||
785 | 75 | exit 0 | 126 | exit 0 |
786 | 76 | 127 | ||
787 | 128 | |||
788 | 77 | %postun | 129 | %postun |
792 | 78 | if [ "$1" -ge 1 ]; then | 130 | %if %{with_systemd} |
793 | 79 | /sbin/service %{name} condrestart > /dev/null 2>&1 | 131 | /bin/systemctl daemon-reload >/dev/null 2>&1 || : |
794 | 80 | fi | 132 | %endif |
795 | 133 | |||
796 | 134 | # Don't auto-restart memcached on upgrade -- let user control when cache flushes | ||
797 | 135 | # if [ "$1" -ge 1 ]; then | ||
798 | 136 | # # upgrade, not install | ||
799 | 137 | # %if %{with_systemd} | ||
800 | 138 | # /bin/systemctl try-restart %{name}.service | ||
801 | 139 | # /bin/systemctl try-restart %{name}@\*.service | ||
802 | 140 | # %else | ||
803 | 141 | # /sbin/service %named condrestart 2>/dev/null || : | ||
804 | 142 | # %endif | ||
805 | 143 | #fi | ||
806 | 144 | |||
807 | 81 | exit 0 | 145 | exit 0 |
808 | 82 | 146 | ||
809 | 83 | 147 | ||
810 | @@ -86,14 +150,24 @@ exit 0 | |||
811 | 86 | %doc AUTHORS ChangeLog COPYING NEWS README.md doc/CONTRIBUTORS doc/*.txt | 150 | %doc AUTHORS ChangeLog COPYING NEWS README.md doc/CONTRIBUTORS doc/*.txt |
812 | 87 | %config(noreplace) %{_sysconfdir}/sysconfig/%{name} | 151 | %config(noreplace) %{_sysconfdir}/sysconfig/%{name} |
813 | 88 | 152 | ||
820 | 89 | %dir %attr(750,nobody,nobody) %{_localstatedir}/run/memcached | 153 | %dir %attr(750,nobody,nobody) %{_localstatedir}/run/%{name} |
821 | 90 | %{_bindir}/memcached-tool | 154 | %{_bindir}/%{name}-tool |
822 | 91 | %{_bindir}/memcached | 155 | %{_bindir}/%{name} |
823 | 92 | %{_mandir}/man1/memcached.1* | 156 | %{_mandir}/man1/%{name}.1* |
824 | 93 | %{_initrddir}/memcached | 157 | %{_includedir}/%{name} |
825 | 94 | %{_includedir}/memcached | 158 | |
826 | 159 | %if %{with_systemd} | ||
827 | 160 | %{_unitdir}/%{name}.service | ||
828 | 161 | %{_unitdir}/%{name}@.service | ||
829 | 162 | %else | ||
830 | 163 | %{_initrddir}/%{name} | ||
831 | 164 | %endif | ||
832 | 95 | 165 | ||
833 | 96 | %changelog | 166 | %changelog |
834 | 167 | * Wed Jul 5 2017 J. Grizzard <jg-github@lupine.org> - 1.4.39 | ||
835 | 168 | - Add systemd-aware build | ||
836 | 169 | - Add both static and instanced versions of memcached unit files | ||
837 | 170 | |||
838 | 97 | * Mon Nov 2 2009 Dormando <dormando@rydia.net> - 1.4.3-1 | 171 | * Mon Nov 2 2009 Dormando <dormando@rydia.net> - 1.4.3-1 |
839 | 98 | - Fix autogen more. | 172 | - Fix autogen more. |
840 | 99 | 173 | ||
841 | @@ -113,7 +187,7 @@ exit 0 | |||
842 | 113 | - above suggestions from Bernard Johnson | 187 | - above suggestions from Bernard Johnson |
843 | 114 | 188 | ||
844 | 115 | * Mon May 7 2007 Paul Lindner <lindner@inuus.com> - 1.2.2-2 | 189 | * Mon May 7 2007 Paul Lindner <lindner@inuus.com> - 1.2.2-2 |
846 | 116 | - Tidiness improvements suggested by Ruben Kerkhof in bugzilla #238994 | 190 | - Tidyness improvements suggested by Ruben Kerkhof in bugzilla #238994 |
847 | 117 | 191 | ||
848 | 118 | * Fri May 4 2007 Paul Lindner <lindner@inuus.com> - 1.2.2-1 | 192 | * Fri May 4 2007 Paul Lindner <lindner@inuus.com> - 1.2.2-1 |
849 | 119 | - Initial spec file created via rpmdev-newspec | 193 | - Initial spec file created via rpmdev-newspec |
850 | diff --git a/memcached_dtrace.d b/memcached_dtrace.d | |||
851 | index 41617ff..3443795 100644 | |||
852 | --- a/memcached_dtrace.d | |||
853 | +++ b/memcached_dtrace.d | |||
854 | @@ -111,19 +111,15 @@ provider memcached { | |||
855 | 111 | * Fired when a new item has been inserted. | 111 | * Fired when a new item has been inserted. |
856 | 112 | * @param key the key just inserted | 112 | * @param key the key just inserted |
857 | 113 | * @param keylen length of the key | 113 | * @param keylen length of the key |
858 | 114 | * @param nokeys the total number of keys currently stored, | ||
859 | 115 | * including the key for which insert was called. | ||
860 | 116 | */ | 114 | */ |
862 | 117 | probe assoc__insert(const char *key, int keylen, int nokeys); | 115 | probe assoc__insert(const char *key, int keylen); |
863 | 118 | 116 | ||
864 | 119 | /** | 117 | /** |
865 | 120 | * Fired when a new item has been removed. | 118 | * Fired when a new item has been removed. |
866 | 121 | * @param key the key just deleted | 119 | * @param key the key just deleted |
867 | 122 | * @param keylen length of the key | 120 | * @param keylen length of the key |
868 | 123 | * @param nokeys the total number of keys currently stored, | ||
869 | 124 | * excluding the key for which delete was called. | ||
870 | 125 | */ | 121 | */ |
872 | 126 | probe assoc__delete(const char *key, int keylen, int nokeys); | 122 | probe assoc__delete(const char *key, int keylen); |
873 | 127 | 123 | ||
874 | 128 | /** | 124 | /** |
875 | 129 | * Fired when an item is linked into the cache. | 125 | * Fired when an item is linked into the cache. |
876 | diff --git a/scripts/memcached-automove-extstore b/scripts/memcached-automove-extstore | |||
877 | index fa7a11c..db66d8c 100755 | |||
878 | --- a/scripts/memcached-automove-extstore | |||
879 | +++ b/scripts/memcached-automove-extstore | |||
880 | @@ -55,17 +55,17 @@ def window_key_check(history, key): | |||
881 | 55 | def determine_move(history, stats, diffs, memfree): | 55 | def determine_move(history, stats, diffs, memfree): |
882 | 56 | """ Figure out of a page move is in order. | 56 | """ Figure out of a page move is in order. |
883 | 57 | 57 | ||
886 | 58 | - we should use as much memory as possible to buffer items, reducing | 58 | - Use as much memory as possible to hold items, reducing the load on |
887 | 59 | the load on flash. | 59 | flash. |
888 | 60 | - tries to keep the global free page pool inbetween poolmin/poolmax. | 60 | - tries to keep the global free page pool inbetween poolmin/poolmax. |
889 | 61 | - avoids flapping as much as possible: | 61 | - avoids flapping as much as possible: |
890 | 62 | - only pull pages off of a class if it hasn't recently evicted or allocated pages. | 62 | - only pull pages off of a class if it hasn't recently evicted or allocated pages. |
892 | 63 | - only pull pages off if a sufficient number of chunks are available. | 63 | - only pull pages off if a sufficient number of free chunks are available. |
893 | 64 | - if global pool is below minimum remove pages from oldest large class. | 64 | - if global pool is below minimum remove pages from oldest large class. |
894 | 65 | - if global pool is above maximum, move pages to youngest large class. | 65 | - if global pool is above maximum, move pages to youngest large class. |
898 | 66 | - re-adjusts number of free chunks once per minute, based on usage. | 66 | - extstore manages a desired number of free chunks in each slab class. |
899 | 67 | - age balancing should move memory around large classes, which then | 67 | - autmover adjusts above limits once per minute based on current sizes. |
900 | 68 | adjusts the per-class free chunk minimums. | 68 | - if youngest is below the age ratio limit of oldest, move a page to it. |
901 | 69 | """ | 69 | """ |
902 | 70 | # rotate windows | 70 | # rotate windows |
903 | 71 | history['w'].append({}) | 71 | history['w'].append({}) |
904 | @@ -88,6 +88,7 @@ def determine_move(history, stats, diffs, memfree): | |||
905 | 88 | pool_high = window_key_check(history, 'slab_pool_high') | 88 | pool_high = window_key_check(history, 'slab_pool_high') |
906 | 89 | for sid, slab in diffs.items(): | 89 | for sid, slab in diffs.items(): |
907 | 90 | small_slab = False | 90 | small_slab = False |
908 | 91 | free_enough = False | ||
909 | 91 | # Only balance larger slab classes | 92 | # Only balance larger slab classes |
910 | 92 | if slab['chunk_size'] < args.size: | 93 | if slab['chunk_size'] < args.size: |
911 | 93 | small_slab = True | 94 | small_slab = True |
912 | @@ -102,7 +103,9 @@ def determine_move(history, stats, diffs, memfree): | |||
913 | 102 | if slab['evicted_d'] > 0: | 103 | if slab['evicted_d'] > 0: |
914 | 103 | w[sid]['dirty'] = 1 | 104 | w[sid]['dirty'] = 1 |
915 | 104 | w[sid]['ev'] = 1 | 105 | w[sid]['ev'] = 1 |
917 | 105 | if slab['free_chunks'] > memfree[sid] and memfree[sid] > 0: | 106 | if slab['free_chunks'] > memfree[sid]: |
918 | 107 | free_enough = True | ||
919 | 108 | if memfree[sid] > 0 and slab['free_chunks'] > (memfree[sid] * 2): | ||
920 | 106 | w[sid]['excess_free'] = 1 | 109 | w[sid]['excess_free'] = 1 |
921 | 107 | w[sid]['age'] = slab['age'] | 110 | w[sid]['age'] = slab['age'] |
922 | 108 | age = window_check(history, sid, 'age') / len(history['w']) | 111 | age = window_check(history, sid, 'age') / len(history['w']) |
923 | @@ -121,24 +124,25 @@ def determine_move(history, stats, diffs, memfree): | |||
924 | 121 | too_free = True | 124 | too_free = True |
925 | 122 | 125 | ||
926 | 123 | # are we the oldest slab class? (and a valid target) | 126 | # are we the oldest slab class? (and a valid target) |
927 | 127 | # don't consider for young if we've recently given it unused memory | ||
928 | 124 | if small_slab == False: | 128 | if small_slab == False: |
929 | 125 | if age > oldest[1] and slab['total_pages'] > MIN_PAGES_FOR_SOURCE: | 129 | if age > oldest[1] and slab['total_pages'] > MIN_PAGES_FOR_SOURCE: |
930 | 126 | oldest = (sid, age) | 130 | oldest = (sid, age) |
931 | 127 | if age < youngest[1] and slab['total_pages'] > 0 \ | 131 | if age < youngest[1] and slab['total_pages'] > 0 \ |
933 | 128 | and window_check(history, sid, 'excess_free') < len(history['w']): | 132 | and window_check(history, sid, 'excess_free') < len(history['w']) \ |
934 | 133 | and not (window_check(history, sid, 'relaxed') and free_enough): | ||
935 | 129 | youngest = (sid, age) | 134 | youngest = (sid, age) |
936 | 130 | 135 | ||
937 | 131 | 136 | ||
938 | 132 | if w.get('slab_pool_high') and youngest[0] != -1: | 137 | if w.get('slab_pool_high') and youngest[0] != -1: |
939 | 133 | # if global pool is too high, feed youngest large class. | 138 | # if global pool is too high, feed youngest large class. |
944 | 134 | # decision = (0, youngest[0]) | 139 | if slab['free_chunks'] <= memfree[youngest[0]]: |
945 | 135 | # No current way to assign directly from global to a class. | 140 | decision = (0, youngest[0]) |
946 | 136 | # minimize the free chunks limiter and re-check. | 141 | w[youngest[0]]['relaxed'] = 1 |
943 | 137 | decision = (youngest[0], -2) | ||
947 | 138 | elif too_free == False and pool_low and oldest[0] != -1: | 142 | elif too_free == False and pool_low and oldest[0] != -1: |
948 | 139 | # if pool is too low, take from oldest large class. | 143 | # if pool is too low, take from oldest large class. |
949 | 140 | if args.verbose: | 144 | if args.verbose: |
951 | 141 | print("oldest: [class: {}] [age: {}]".format(int(oldest[0]), oldest[1])) | 145 | print("oldest: [class: {}] [age: {:.2f}]".format(int(oldest[0]), oldest[1])) |
952 | 142 | decision = (oldest[0], 0) | 146 | decision = (oldest[0], 0) |
953 | 143 | elif too_free == False and youngest[0] != -1 and oldest[0] != -1 and youngest[0] != oldest[0]: | 147 | elif too_free == False and youngest[0] != -1 and oldest[0] != -1 and youngest[0] != oldest[0]: |
954 | 144 | # youngest is outside of the tolerance ratio, move a page around. | 148 | # youngest is outside of the tolerance ratio, move a page around. |
955 | @@ -148,8 +152,10 @@ def determine_move(history, stats, diffs, memfree): | |||
956 | 148 | 152 | ||
957 | 149 | slab = diffs[youngest[0]] | 153 | slab = diffs[youngest[0]] |
958 | 150 | #print("F:{} L:{} Y:{} R:{}".format(slab['free_chunks'], memfree[youngest[0]], int(youngest[1]), int(oldest[1] * args.ratio))) | 154 | #print("F:{} L:{} Y:{} R:{}".format(slab['free_chunks'], memfree[youngest[0]], int(youngest[1]), int(oldest[1] * args.ratio))) |
961 | 151 | if (slab['free_chunks'] <= memfree[youngest[0]]) and (youngest[1] < oldest[1] * args.ratio): | 155 | if youngest[1] < oldest[1] * args.ratio: |
962 | 152 | decision = (oldest[0], youngest[0]) | 156 | w[youngest[0]]['relaxed'] = 1 |
963 | 157 | if slab['free_chunks'] <= memfree[youngest[0]]: | ||
964 | 158 | decision = (0, youngest[0]) | ||
965 | 153 | 159 | ||
966 | 154 | if (len(history['w']) >= args.window): | 160 | if (len(history['w']) >= args.window): |
967 | 155 | return decision | 161 | return decision |
968 | @@ -289,27 +295,16 @@ while True: | |||
969 | 289 | (diffs, totals) = diff_stats(stats_pre, stats_post) | 295 | (diffs, totals) = diff_stats(stats_pre, stats_post) |
970 | 290 | #if args.verbose: | 296 | #if args.verbose: |
971 | 291 | # show_detail(diffs, totals) | 297 | # show_detail(diffs, totals) |
972 | 292 | if (last_memfree_check < time() - 60) and totals.get('total_pages'): | ||
973 | 293 | memfree = memfree_check(s, diffs, totals) | ||
974 | 294 | last_memfree_check = time() | ||
975 | 295 | decision = (-1, -1) | ||
976 | 296 | if int(stats['evictions']) > 0: | 298 | if int(stats['evictions']) > 0: |
977 | 299 | if (last_memfree_check < time() - 60) and totals.get('total_pages'): | ||
978 | 300 | memfree = memfree_check(s, diffs, totals) | ||
979 | 301 | last_memfree_check = time() | ||
980 | 302 | decision = (-1, -1) | ||
981 | 297 | decision = determine_move(history, stats, diffs, memfree) | 303 | decision = determine_move(history, stats, diffs, memfree) |
982 | 298 | if int(decision[0]) > 0 and int(decision[1]) >= 0: | 304 | if int(decision[0]) > 0 and int(decision[1]) >= 0: |
983 | 299 | print("moving page from, to:", decision) | 305 | print("moving page from, to:", decision) |
984 | 300 | if args.automove: | 306 | if args.automove: |
985 | 301 | run_move(s, decision) | 307 | run_move(s, decision) |
986 | 302 | elif int(decision[0]) > 0 and decision[1] == -2: | ||
987 | 303 | # we've been told to zero out the memory limit. | ||
988 | 304 | # let the memfree check run "soon". | ||
989 | 305 | # this (purposefully) can slowly remove limits on | ||
990 | 306 | # multiple classes if global pool stays too high. | ||
991 | 307 | last_memfree_check = time() - 58 | ||
992 | 308 | s.write("extstore free_memchunks {} {}\r\n".format(decision[0], 0)) | ||
993 | 309 | s.readline() | ||
994 | 310 | if args.verbose: | ||
995 | 311 | print("relaxing free:", decision[0]) | ||
996 | 312 | |||
997 | 313 | 308 | ||
998 | 314 | # Minimize sleeping if we just moved a page to global pool. | 309 | # Minimize sleeping if we just moved a page to global pool. |
999 | 315 | # Improves responsiveness during flushes/quick changes. | 310 | # Improves responsiveness during flushes/quick changes. |
1000 | diff --git a/scripts/memcached.service b/scripts/memcached.service | |||
1001 | index 2bfbb67..88a4b8a 100644 | |||
1002 | --- a/scripts/memcached.service | |||
1003 | +++ b/scripts/memcached.service | |||
1004 | @@ -1,10 +1,10 @@ | |||
1005 | 1 | # It's not recommended to modify this file in-place, because it will be | 1 | # It's not recommended to modify this file in-place, because it will be |
1006 | 2 | # overwritten during upgrades. If you want to customize, the best | 2 | # overwritten during upgrades. If you want to customize, the best |
1007 | 3 | # way is to use the "systemctl edit" command to create an override unit. | 3 | # way is to use the "systemctl edit" command to create an override unit. |
1009 | 4 | 4 | # | |
1010 | 5 | # For example, to pass additional options, create an override unit | 5 | # For example, to pass additional options, create an override unit |
1011 | 6 | # (as is done by systemctl edit) and enter the following: | 6 | # (as is done by systemctl edit) and enter the following: |
1013 | 7 | 7 | # | |
1014 | 8 | # [Service] | 8 | # [Service] |
1015 | 9 | # Environment=OPTIONS="-l 127.0.0.1,::1" | 9 | # Environment=OPTIONS="-l 127.0.0.1,::1" |
1016 | 10 | 10 | ||
1017 | @@ -17,56 +17,68 @@ After=network.target | |||
1018 | 17 | EnvironmentFile=/etc/sysconfig/memcached | 17 | EnvironmentFile=/etc/sysconfig/memcached |
1019 | 18 | ExecStart=/usr/bin/memcached -p ${PORT} -u ${USER} -m ${CACHESIZE} -c ${MAXCONN} $OPTIONS | 18 | ExecStart=/usr/bin/memcached -p ${PORT} -u ${USER} -m ${CACHESIZE} -c ${MAXCONN} $OPTIONS |
1020 | 19 | 19 | ||
1024 | 20 | # Set up a new file system namespace and mounts private /tmp and /var/tmp directories | 20 | # Set up a new file system namespace and mounts private /tmp and /var/tmp |
1025 | 21 | # so this service cannot access the global directories and other processes cannot | 21 | # directories so this service cannot access the global directories and |
1026 | 22 | # access this service's directories. | 22 | # other processes cannot access this service's directories. |
1027 | 23 | PrivateTmp=true | 23 | PrivateTmp=true |
1028 | 24 | 24 | ||
1030 | 25 | # Mounts the /usr, /boot, and /etc directories read-only for processes invoked by this unit. | 25 | # Mounts the /usr, /boot, and /etc directories read-only for processes |
1031 | 26 | # invoked by this unit. | ||
1032 | 26 | ProtectSystem=full | 27 | ProtectSystem=full |
1033 | 27 | 28 | ||
1035 | 28 | # Ensures that the service process and all its children can never gain new privileges | 29 | # Ensures that the service process and all its children can never gain new |
1036 | 30 | # privileges | ||
1037 | 29 | NoNewPrivileges=true | 31 | NoNewPrivileges=true |
1038 | 30 | 32 | ||
1042 | 31 | # Sets up a new /dev namespace for the executed processes and only adds API pseudo devices | 33 | # Sets up a new /dev namespace for the executed processes and only adds API |
1043 | 32 | # such as /dev/null, /dev/zero or /dev/random (as well as the pseudo TTY subsystem) to it, | 34 | # pseudo devices such as /dev/null, /dev/zero or /dev/random (as well as |
1044 | 33 | # but no physical devices such as /dev/sda. | 35 | # the pseudo TTY subsystem) to it, but no physical devices such as /dev/sda. |
1045 | 34 | PrivateDevices=true | 36 | PrivateDevices=true |
1046 | 35 | 37 | ||
1047 | 36 | # Required for dropping privileges and running as a different user | 38 | # Required for dropping privileges and running as a different user |
1048 | 37 | CapabilityBoundingSet=CAP_SETGID CAP_SETUID CAP_SYS_RESOURCE | 39 | CapabilityBoundingSet=CAP_SETGID CAP_SETUID CAP_SYS_RESOURCE |
1049 | 38 | 40 | ||
1053 | 39 | # Attempts to create memory mappings that are writable and executable at the same time, | 41 | # Restricts the set of socket address families accessible to the processes |
1054 | 40 | # or to change existing memory mappings to become executable are prohibited. | 42 | # of this unit. Protects against vulnerabilities such as CVE-2016-8655 |
1055 | 41 | MemoryDenyWriteExecute=true | 43 | RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX |
1056 | 42 | 44 | ||
1057 | 43 | # Explicit module loading will be denied. This allows to turn off module load and unload | ||
1058 | 44 | # operations on modular kernels. It is recommended to turn this on for most services that | ||
1059 | 45 | # do not need special file systems or extra kernel modules to work. | ||
1060 | 46 | ProtectKernelModules=true | ||
1061 | 47 | 45 | ||
1068 | 48 | # Kernel variables accessible through /proc/sys, /sys, /proc/sysrq-trigger, /proc/latency_stats, | 46 | # Some security features are not in the older versions of systemd used by |
1069 | 49 | # /proc/acpi, /proc/timer_stats, /proc/fs and /proc/irq will be made read-only to all processes | 47 | # e.g. RHEL7/CentOS 7. The below settings are automatically edited at package |
1070 | 50 | # of the unit. Usually, tunable kernel variables should only be written at boot-time, with the | 48 | # build time to uncomment them if the target platform supports them. |
1065 | 51 | # sysctl.d(5) mechanism. Almost no services need to write to these at runtime; it is hence | ||
1066 | 52 | # recommended to turn this on for most services. | ||
1067 | 53 | ProtectKernelTunables=true | ||
1071 | 54 | 49 | ||
1077 | 55 | # The Linux Control Groups (cgroups(7)) hierarchies accessible through /sys/fs/cgroup will be | 50 | # Attempts to create memory mappings that are writable and executable at |
1078 | 56 | # made read-only to all processes of the unit. Except for container managers no services should | 51 | # the same time, or to change existing memory mappings to become executable |
1079 | 57 | # require write access to the control groups hierarchies; it is hence recommended to turn this on | 52 | # are prohibited. |
1080 | 58 | # for most services | 53 | ##safer##MemoryDenyWriteExecute=true |
1076 | 59 | ProtectControlGroups=true | ||
1081 | 60 | 54 | ||
1084 | 61 | # Any attempts to enable realtime scheduling in a process of the unit are refused. | 55 | # Explicit module loading will be denied. This allows to turn off module |
1085 | 62 | RestrictRealtime=true | 56 | # load and unload operations on modular kernels. It is recommended to turn |
1086 | 57 | # this on for most services that do not need special file systems or extra | ||
1087 | 58 | # kernel modules to work. | ||
1088 | 59 | ##safer##ProtectKernelModules=true | ||
1089 | 63 | 60 | ||
1093 | 64 | # Restricts the set of socket address families accessible to the processes of this unit. | 61 | # Kernel variables accessible through /proc/sys, /sys, /proc/sysrq-trigger, |
1094 | 65 | # Protects against vulnerabilities such as CVE-2016-8655 | 62 | # /proc/latency_stats, /proc/acpi, /proc/timer_stats, /proc/fs and /proc/irq |
1095 | 66 | RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX | 63 | # will be made read-only to all processes of the unit. Usually, tunable |
1096 | 64 | # kernel variables should only be written at boot-time, with the sysctl.d(5) | ||
1097 | 65 | # mechanism. Almost no services need to write to these at runtime; it is hence | ||
1098 | 66 | # recommended to turn this on for most services. | ||
1099 | 67 | ##safer##ProtectKernelTunables=true | ||
1100 | 68 | |||
1101 | 69 | # The Linux Control Groups (cgroups(7)) hierarchies accessible through | ||
1102 | 70 | # /sys/fs/cgroup will be made read-only to all processes of the unit. | ||
1103 | 71 | # Except for container managers no services should require write access | ||
1104 | 72 | # to the control groups hierarchies; it is hence recommended to turn this | ||
1105 | 73 | # on for most services | ||
1106 | 74 | ##safer##ProtectControlGroups=true | ||
1107 | 75 | |||
1108 | 76 | # Any attempts to enable realtime scheduling in a process of the unit are | ||
1109 | 77 | # refused. | ||
1110 | 78 | ##safer##RestrictRealtime=true | ||
1111 | 67 | 79 | ||
1112 | 68 | # Takes away the ability to create or manage any kind of namespace | 80 | # Takes away the ability to create or manage any kind of namespace |
1114 | 69 | RestrictNamespaces=true | 81 | ##safer##RestrictNamespaces=true |
1115 | 70 | 82 | ||
1116 | 71 | [Install] | 83 | [Install] |
1117 | 72 | WantedBy=multi-user.target | 84 | WantedBy=multi-user.target |
1118 | diff --git a/scripts/memcached.sysconfig b/scripts/memcached.sysconfig | |||
1119 | 73 | new file mode 100644 | 85 | new file mode 100644 |
1120 | index 0000000..bd46483 | |||
1121 | --- /dev/null | |||
1122 | +++ b/scripts/memcached.sysconfig | |||
1123 | @@ -0,0 +1,10 @@ | |||
1124 | 1 | # These defaults will be used by every memcached instance, unless overridden | ||
1125 | 2 | # by values in /etc/sysconfig/memcached.<port> | ||
1126 | 3 | USER="nobody" | ||
1127 | 4 | MAXCONN="1024" | ||
1128 | 5 | CACHESIZE="64" | ||
1129 | 6 | OPTIONS="" | ||
1130 | 7 | |||
1131 | 8 | # The PORT variable will only be used by memcached.service, not by | ||
1132 | 9 | # memcached@xxxxx services, which will use the xxxxx | ||
1133 | 10 | PORT="11211" | ||
1134 | diff --git a/scripts/memcached@.service b/scripts/memcached@.service | |||
1135 | 0 | new file mode 100644 | 11 | new file mode 100644 |
1136 | index 0000000..4e9f1d7 | |||
1137 | --- /dev/null | |||
1138 | +++ b/scripts/memcached@.service | |||
1139 | @@ -0,0 +1,89 @@ | |||
1140 | 1 | # It's not recommended to modify this file in-place, because it will be | ||
1141 | 2 | # overwritten during upgrades. If you want to customize, the best | ||
1142 | 3 | # way is to use the "systemctl edit" command to create an override unit. | ||
1143 | 4 | # | ||
1144 | 5 | # For example, to pass additional options, create an override unit | ||
1145 | 6 | # (as is done by systemctl edit) and enter the following: | ||
1146 | 7 | # | ||
1147 | 8 | # [Service] | ||
1148 | 9 | # Environment=OPTIONS="-l 127.0.0.1,::1" | ||
1149 | 10 | # | ||
1150 | 11 | # To use the "instanced" version of this, just start 'memcached@11211' or | ||
1151 | 12 | # whatever port you'd like. If /etc/sysconfig/memcached.<port> exists, it | ||
1152 | 13 | # will be read first, so you can set different parameters for a given | ||
1153 | 14 | # instance. | ||
1154 | 15 | |||
1155 | 16 | [Unit] | ||
1156 | 17 | Description=memcached daemon | ||
1157 | 18 | After=network.target | ||
1158 | 19 | |||
1159 | 20 | [Service] | ||
1160 | 21 | EnvironmentFile=/etc/sysconfig/memcached | ||
1161 | 22 | EnvironmentFile=-/etc/sysconfig/memcached.%i | ||
1162 | 23 | ExecStart=/usr/bin/memcached -p %i -u ${USER} -m ${CACHESIZE} -c ${MAXCONN} $OPTIONS | ||
1163 | 24 | |||
1164 | 25 | # Set up a new file system namespace and mounts private /tmp and /var/tmp | ||
1165 | 26 | # directories so this service cannot access the global directories and | ||
1166 | 27 | # other processes cannot access this service's directories. | ||
1167 | 28 | PrivateTmp=true | ||
1168 | 29 | |||
1169 | 30 | # Mounts the /usr, /boot, and /etc directories read-only for processes | ||
1170 | 31 | # invoked by this unit. | ||
1171 | 32 | ProtectSystem=full | ||
1172 | 33 | |||
1173 | 34 | # Ensures that the service process and all its children can never gain new | ||
1174 | 35 | # privileges | ||
1175 | 36 | NoNewPrivileges=true | ||
1176 | 37 | |||
1177 | 38 | # Sets up a new /dev namespace for the executed processes and only adds API | ||
1178 | 39 | # pseudo devices such as /dev/null, /dev/zero or /dev/random (as well as | ||
1179 | 40 | # the pseudo TTY subsystem) to it, but no physical devices such as /dev/sda. | ||
1180 | 41 | PrivateDevices=true | ||
1181 | 42 | |||
1182 | 43 | # Required for dropping privileges and running as a different user | ||
1183 | 44 | CapabilityBoundingSet=CAP_SETGID CAP_SETUID CAP_SYS_RESOURCE | ||
1184 | 45 | |||
1185 | 46 | # Restricts the set of socket address families accessible to the processes | ||
1186 | 47 | # of this unit. Protects against vulnerabilities such as CVE-2016-8655 | ||
1187 | 48 | RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX | ||
1188 | 49 | |||
1189 | 50 | |||
1190 | 51 | # Some security features are not in the older versions of systemd used by | ||
1191 | 52 | # e.g. RHEL7/CentOS 7. The below settings are automatically edited at package | ||
1192 | 53 | # build time to uncomment them if the target platform supports them. | ||
1193 | 54 | |||
1194 | 55 | # Attempts to create memory mappings that are writable and executable at | ||
1195 | 56 | # the same time, or to change existing memory mappings to become executable | ||
1196 | 57 | # are prohibited. | ||
1197 | 58 | ##safer##MemoryDenyWriteExecute=true | ||
1198 | 59 | |||
1199 | 60 | # Explicit module loading will be denied. This allows to turn off module | ||
1200 | 61 | # load and unload operations on modular kernels. It is recommended to turn | ||
1201 | 62 | # this on for most services that do not need special file systems or extra | ||
1202 | 63 | # kernel modules to work. | ||
1203 | 64 | ##safer##ProtectKernelModules=true | ||
1204 | 65 | |||
1205 | 66 | # Kernel variables accessible through /proc/sys, /sys, /proc/sysrq-trigger, | ||
1206 | 67 | # /proc/latency_stats, /proc/acpi, /proc/timer_stats, /proc/fs and /proc/irq | ||
1207 | 68 | # will be made read-only to all processes of the unit. Usually, tunable | ||
1208 | 69 | # kernel variables should only be written at boot-time, with the sysctl.d(5) | ||
1209 | 70 | # mechanism. Almost no services need to write to these at runtime; it is hence | ||
1210 | 71 | # recommended to turn this on for most services. | ||
1211 | 72 | ##safer##ProtectKernelTunables=true | ||
1212 | 73 | |||
1213 | 74 | # The Linux Control Groups (cgroups(7)) hierarchies accessible through | ||
1214 | 75 | # /sys/fs/cgroup will be made read-only to all processes of the unit. | ||
1215 | 76 | # Except for container managers no services should require write access | ||
1216 | 77 | # to the control groups hierarchies; it is hence recommended to turn this | ||
1217 | 78 | # on for most services | ||
1218 | 79 | ##safer##ProtectControlGroups=true | ||
1219 | 80 | |||
1220 | 81 | # Any attempts to enable realtime scheduling in a process of the unit are | ||
1221 | 82 | # refused. | ||
1222 | 83 | ##safer##RestrictRealtime=true | ||
1223 | 84 | |||
1224 | 85 | # Takes away the ability to create or manage any kind of namespace | ||
1225 | 86 | ##safer##RestrictNamespaces=true | ||
1226 | 87 | |||
1227 | 88 | [Install] | ||
1228 | 89 | WantedBy=multi-user.target | ||
1229 | diff --git a/slab_automove_extstore.c b/slab_automove_extstore.c | |||
1230 | index d9b62b9..a3012d7 100644 | |||
1231 | --- a/slab_automove_extstore.c | |||
1232 | +++ b/slab_automove_extstore.c | |||
1233 | @@ -20,6 +20,7 @@ struct window_data { | |||
1234 | 20 | uint64_t dirty; | 20 | uint64_t dirty; |
1235 | 21 | uint64_t evicted; | 21 | uint64_t evicted; |
1236 | 22 | unsigned int excess_free; | 22 | unsigned int excess_free; |
1237 | 23 | unsigned int relaxed; | ||
1238 | 23 | }; | 24 | }; |
1239 | 24 | 25 | ||
1240 | 25 | struct window_global { | 26 | struct window_global { |
1241 | @@ -90,6 +91,7 @@ static void window_sum(struct window_data *wd, struct window_data *w, | |||
1242 | 90 | w->dirty += d->dirty; | 91 | w->dirty += d->dirty; |
1243 | 91 | w->evicted += d->evicted; | 92 | w->evicted += d->evicted; |
1244 | 92 | w->excess_free += d->excess_free; | 93 | w->excess_free += d->excess_free; |
1245 | 94 | w->relaxed += d->relaxed; | ||
1246 | 93 | } | 95 | } |
1247 | 94 | } | 96 | } |
1248 | 95 | 97 | ||
1249 | @@ -121,6 +123,15 @@ static void global_pool_check(slab_automove *a) { | |||
1250 | 121 | } | 123 | } |
1251 | 122 | } | 124 | } |
1252 | 123 | 125 | ||
1253 | 126 | /* A percentage of memory is configured to be held "free" as buffers for the | ||
1254 | 127 | * external storage system. | ||
1255 | 128 | * % of global memory is desired in the global page pool | ||
1256 | 129 | * each slab class has a % of free chunks desired based on how much memory is | ||
1257 | 130 | * currently in the class. This allows time for extstore to flush data when | ||
1258 | 131 | * spikes or waves of set data arrive. | ||
1259 | 132 | * The global page pool reserve acts as a secondary buffer for any slab class, | ||
1260 | 133 | * which helps absorb shifts in which class is active. | ||
1261 | 134 | */ | ||
1262 | 124 | static void memcheck(slab_automove *a) { | 135 | static void memcheck(slab_automove *a) { |
1263 | 125 | unsigned int total_pages = 0; | 136 | unsigned int total_pages = 0; |
1264 | 126 | if (current_time < a->last_memcheck_run + MEMCHECK_PERIOD) | 137 | if (current_time < a->last_memcheck_run + MEMCHECK_PERIOD) |
1265 | @@ -143,6 +154,11 @@ static void memcheck(slab_automove *a) { | |||
1266 | 143 | a->free_mem[0] = total_pages * a->free_ratio; | 154 | a->free_mem[0] = total_pages * a->free_ratio; |
1267 | 144 | } | 155 | } |
1268 | 145 | 156 | ||
1269 | 157 | static struct window_data *get_window_data(slab_automove *a, int class) { | ||
1270 | 158 | int w_offset = class * a->window_size; | ||
1271 | 159 | return &a->window_data[w_offset + (a->window_cur % a->window_size)]; | ||
1272 | 160 | } | ||
1273 | 161 | |||
1274 | 146 | void slab_automove_extstore_run(void *arg, int *src, int *dst) { | 162 | void slab_automove_extstore_run(void *arg, int *src, int *dst) { |
1275 | 147 | slab_automove *a = (slab_automove *)arg; | 163 | slab_automove *a = (slab_automove *)arg; |
1276 | 148 | int n; | 164 | int n; |
1277 | @@ -170,15 +186,16 @@ void slab_automove_extstore_run(void *arg, int *src, int *dst) { | |||
1278 | 170 | for (n = POWER_SMALLEST; n < MAX_NUMBER_OF_SLAB_CLASSES; n++) { | 186 | for (n = POWER_SMALLEST; n < MAX_NUMBER_OF_SLAB_CLASSES; n++) { |
1279 | 171 | bool small_slab = a->sam_before[n].chunk_size < a->item_size | 187 | bool small_slab = a->sam_before[n].chunk_size < a->item_size |
1280 | 172 | ? true : false; | 188 | ? true : false; |
1283 | 173 | int w_offset = n * a->window_size; | 189 | bool free_enough = false; |
1284 | 174 | struct window_data *wd = &a->window_data[w_offset + (a->window_cur % a->window_size)]; | 190 | struct window_data *wd = get_window_data(a, n); |
1285 | 175 | // summarize the window-up-to-now. | 191 | // summarize the window-up-to-now. |
1286 | 176 | memset(&w_sum, 0, sizeof(struct window_data)); | 192 | memset(&w_sum, 0, sizeof(struct window_data)); |
1287 | 193 | int w_offset = n * a->window_size; | ||
1288 | 177 | window_sum(&a->window_data[w_offset], &w_sum, a->window_size); | 194 | window_sum(&a->window_data[w_offset], &w_sum, a->window_size); |
1289 | 178 | memset(wd, 0, sizeof(struct window_data)); | 195 | memset(wd, 0, sizeof(struct window_data)); |
1290 | 179 | 196 | ||
1293 | 180 | // if page delta, or evicted delta, mark window dirty | 197 | // if page delta, oom, or evicted delta, mark window dirty |
1294 | 181 | // (or outofmemory) | 198 | // classes marked dirty cannot donate memory back to global pool. |
1295 | 182 | if (a->iam_after[n].evicted - a->iam_before[n].evicted > 0 || | 199 | if (a->iam_after[n].evicted - a->iam_before[n].evicted > 0 || |
1296 | 183 | a->iam_after[n].outofmemory - a->iam_before[n].outofmemory > 0) { | 200 | a->iam_after[n].outofmemory - a->iam_before[n].outofmemory > 0) { |
1297 | 184 | wd->evicted = 1; | 201 | wd->evicted = 1; |
1298 | @@ -188,7 +205,14 @@ void slab_automove_extstore_run(void *arg, int *src, int *dst) { | |||
1299 | 188 | wd->dirty = 1; | 205 | wd->dirty = 1; |
1300 | 189 | } | 206 | } |
1301 | 190 | // Mark excess free if we're over the free mem limit for too long. | 207 | // Mark excess free if we're over the free mem limit for too long. |
1303 | 191 | if (a->sam_after[n].free_chunks > a->free_mem[n] && a->free_mem[n] > 0) { | 208 | // "free_enough" means it is either wobbling, recently received a new |
1304 | 209 | // page of memory, or the crawler is freeing memory. | ||
1305 | 210 | if (a->sam_after[n].free_chunks > a->free_mem[n]) { | ||
1306 | 211 | free_enough = true; | ||
1307 | 212 | } | ||
1308 | 213 | // double the free requirements means we may have memory we can | ||
1309 | 214 | // reclaim to global, if it stays this way for the whole window. | ||
1310 | 215 | if (a->sam_after[n].free_chunks > (a->free_mem[n] * 2) && a->free_mem[n] > 0) { | ||
1311 | 192 | wd->excess_free = 1; | 216 | wd->excess_free = 1; |
1312 | 193 | } | 217 | } |
1313 | 194 | 218 | ||
1314 | @@ -198,7 +222,9 @@ void slab_automove_extstore_run(void *arg, int *src, int *dst) { | |||
1315 | 198 | // grab age as average of window total | 222 | // grab age as average of window total |
1316 | 199 | uint64_t age = w_sum.age / a->window_size; | 223 | uint64_t age = w_sum.age / a->window_size; |
1317 | 200 | 224 | ||
1319 | 201 | // if > N free chunks and not dirty, make decision. | 225 | // if > N free chunks and not dirty, reclaim memory |
1320 | 226 | // small slab classes aren't age balanced and rely more on global | ||
1321 | 227 | // pool. reclaim them more aggressively. | ||
1322 | 202 | if (a->sam_after[n].free_chunks > a->sam_after[n].chunks_per_page * MIN_PAGES_FOR_RECLAIM | 228 | if (a->sam_after[n].free_chunks > a->sam_after[n].chunks_per_page * MIN_PAGES_FOR_RECLAIM |
1323 | 203 | && w_sum.dirty == 0) { | 229 | && w_sum.dirty == 0) { |
1324 | 204 | if (small_slab) { | 230 | if (small_slab) { |
1325 | @@ -214,19 +240,22 @@ void slab_automove_extstore_run(void *arg, int *src, int *dst) { | |||
1326 | 214 | } | 240 | } |
1327 | 215 | } | 241 | } |
1328 | 216 | 242 | ||
1336 | 217 | // if oldest and have enough pages, is oldest | 243 | if (!small_slab) { |
1337 | 218 | if (!small_slab | 244 | // if oldest and have enough pages, is oldest |
1338 | 219 | && age > oldest_age | 245 | if (age > oldest_age |
1339 | 220 | && a->sam_after[n].total_pages > MIN_PAGES_FOR_SOURCE) { | 246 | && a->sam_after[n].total_pages > MIN_PAGES_FOR_SOURCE) { |
1340 | 221 | oldest = n; | 247 | oldest = n; |
1341 | 222 | oldest_age = age; | 248 | oldest_age = age; |
1342 | 223 | } | 249 | } |
1343 | 224 | 250 | ||
1349 | 225 | // don't count as youngest if it hasn't been using new chunks. | 251 | // don't count as youngest if it hasn't been using new chunks. |
1350 | 226 | if (!small_slab && age < youngest_age && a->sam_after[n].total_pages != 0 | 252 | // (if it was relaxed recently, and is currently "free enough") |
1351 | 227 | && w_sum.excess_free < a->window_size) { | 253 | if (age < youngest_age && a->sam_after[n].total_pages != 0 |
1352 | 228 | youngest = n; | 254 | && w_sum.excess_free < a->window_size |
1353 | 229 | youngest_age = age; | 255 | && !(w_sum.relaxed && free_enough)) { |
1354 | 256 | youngest = n; | ||
1355 | 257 | youngest_age = age; | ||
1356 | 258 | } | ||
1357 | 230 | } | 259 | } |
1358 | 231 | } | 260 | } |
1359 | 232 | 261 | ||
1360 | @@ -239,28 +268,29 @@ void slab_automove_extstore_run(void *arg, int *src, int *dst) { | |||
1361 | 239 | return; | 268 | return; |
1362 | 240 | 269 | ||
1363 | 241 | if (wg_sum.pool_high >= a->window_size && !wg_sum.pool_low && youngest != -1) { | 270 | if (wg_sum.pool_high >= a->window_size && !wg_sum.pool_low && youngest != -1) { |
1377 | 242 | /**src = 0; | 271 | if (a->sam_after[youngest].free_chunks <= a->free_mem[youngest]) { |
1378 | 243 | *dst = youngest;*/ | 272 | *src = 0; |
1379 | 244 | /* TODO: No current way to directly assign page from 0 to elsewhere. | 273 | *dst = youngest; |
1380 | 245 | * Do a hack by setting the youngest's free mem limiter to | 274 | } |
1381 | 246 | * zero and re-running memcheck in the next second. | 275 | struct window_data *wd = get_window_data(a, youngest); |
1382 | 247 | * If set rates are very high and the pool is too low, this can bottom | 276 | // "relaxing" here and below allows us to skip classes which will |
1383 | 248 | * out... | 277 | // never grow or are growing slowly, more quickly finding other |
1384 | 249 | */ | 278 | // classes which violate the age ratio. |
1385 | 250 | // schedule a memcheck run for "soon" to keep the limit zeroed out | 279 | wd->relaxed = 1; |
1373 | 251 | // while the pool stays too high. This will also allow multiple | ||
1374 | 252 | // classes to zero out over time. | ||
1375 | 253 | a->last_memcheck_run = current_time - (MEMCHECK_PERIOD - 2); | ||
1376 | 254 | a->settings->ext_free_memchunks[youngest] = 0; | ||
1386 | 255 | } else if (!too_free && wg_sum.pool_low && oldest != -1) { | 280 | } else if (!too_free && wg_sum.pool_low && oldest != -1) { |
1387 | 256 | *src = oldest; | 281 | *src = oldest; |
1388 | 257 | *dst = 0; | 282 | *dst = 0; |
1389 | 258 | } else if (!too_free && youngest != -1 && oldest != -1 && youngest != oldest) { | 283 | } else if (!too_free && youngest != -1 && oldest != -1 && youngest != oldest) { |
1390 | 259 | // if we have a youngest and oldest, and oldest is outside the ratio. | 284 | // if we have a youngest and oldest, and oldest is outside the ratio. |
1395 | 260 | if (a->sam_after[youngest].free_chunks <= a->free_mem[youngest] | 285 | if (youngest_age < ((double)oldest_age * a->max_age_ratio)) { |
1396 | 261 | && youngest_age < ((double)oldest_age * a->max_age_ratio)) { | 286 | struct window_data *wd = get_window_data(a, youngest); |
1397 | 262 | *src = oldest; | 287 | wd->relaxed = 1; |
1398 | 263 | *dst = youngest; | 288 | // only actually assign more memory if it's absorbed what it has |
1399 | 289 | if (a->sam_after[youngest].free_chunks <= a->free_mem[youngest]) { | ||
1400 | 290 | *src = 0; | ||
1401 | 291 | *dst = youngest; | ||
1402 | 292 | |||
1403 | 293 | } | ||
1404 | 264 | } | 294 | } |
1405 | 265 | } | 295 | } |
1406 | 266 | return; | 296 | return; |
1407 | diff --git a/slabs.c b/slabs.c | |||
1408 | index cedb1e8..200d575 100644 | |||
1409 | --- a/slabs.c | |||
1410 | +++ b/slabs.c | |||
1411 | @@ -678,7 +678,7 @@ static int slab_rebalance_start(void) { | |||
1412 | 678 | 678 | ||
1413 | 679 | pthread_mutex_lock(&slabs_lock); | 679 | pthread_mutex_lock(&slabs_lock); |
1414 | 680 | 680 | ||
1416 | 681 | if (slab_rebal.s_clsid < POWER_SMALLEST || | 681 | if (slab_rebal.s_clsid < SLAB_GLOBAL_PAGE_POOL || |
1417 | 682 | slab_rebal.s_clsid > power_largest || | 682 | slab_rebal.s_clsid > power_largest || |
1418 | 683 | slab_rebal.d_clsid < SLAB_GLOBAL_PAGE_POOL || | 683 | slab_rebal.d_clsid < SLAB_GLOBAL_PAGE_POOL || |
1419 | 684 | slab_rebal.d_clsid > power_largest || | 684 | slab_rebal.d_clsid > power_largest || |
1420 | @@ -707,8 +707,11 @@ static int slab_rebalance_start(void) { | |||
1421 | 707 | (s_cls->size * s_cls->perslab); | 707 | (s_cls->size * s_cls->perslab); |
1422 | 708 | slab_rebal.slab_pos = slab_rebal.slab_start; | 708 | slab_rebal.slab_pos = slab_rebal.slab_start; |
1423 | 709 | slab_rebal.done = 0; | 709 | slab_rebal.done = 0; |
1424 | 710 | // Don't need to do chunk move work if page is in global pool. | ||
1425 | 711 | if (slab_rebal.s_clsid == SLAB_GLOBAL_PAGE_POOL) { | ||
1426 | 712 | slab_rebal.done = 1; | ||
1427 | 713 | } | ||
1428 | 710 | 714 | ||
1429 | 711 | /* Also tells do_item_get to search for items in this slab */ | ||
1430 | 712 | slab_rebalance_signal = 2; | 715 | slab_rebalance_signal = 2; |
1431 | 713 | 716 | ||
1432 | 714 | if (settings.verbose > 1) { | 717 | if (settings.verbose > 1) { |
1433 | @@ -862,7 +865,9 @@ static int slab_rebalance_move(void) { | |||
1434 | 862 | // Only safe to hold slabs lock because refcount | 865 | // Only safe to hold slabs lock because refcount |
1435 | 863 | // can't drop to 0 until we release item lock. | 866 | // can't drop to 0 until we release item lock. |
1436 | 864 | STORAGE_delete(storage, it); | 867 | STORAGE_delete(storage, it); |
1437 | 868 | pthread_mutex_unlock(&slabs_lock); | ||
1438 | 865 | do_item_unlink(it, hv); | 869 | do_item_unlink(it, hv); |
1439 | 870 | pthread_mutex_lock(&slabs_lock); | ||
1440 | 866 | } | 871 | } |
1441 | 867 | status = MOVE_BUSY; | 872 | status = MOVE_BUSY; |
1442 | 868 | } else { | 873 | } else { |
1443 | @@ -1187,7 +1192,7 @@ static enum reassign_result_type do_slabs_reassign(int src, int dst) { | |||
1444 | 1187 | /* TODO: If we end up back at -1, return a new error type */ | 1192 | /* TODO: If we end up back at -1, return a new error type */ |
1445 | 1188 | } | 1193 | } |
1446 | 1189 | 1194 | ||
1448 | 1190 | if (src < POWER_SMALLEST || src > power_largest || | 1195 | if (src < SLAB_GLOBAL_PAGE_POOL || src > power_largest || |
1449 | 1191 | dst < SLAB_GLOBAL_PAGE_POOL || dst > power_largest) | 1196 | dst < SLAB_GLOBAL_PAGE_POOL || dst > power_largest) |
1450 | 1192 | return REASSIGN_BADCLASS; | 1197 | return REASSIGN_BADCLASS; |
1451 | 1193 | 1198 | ||
1452 | diff --git a/t/issue_67.t b/t/issue_67.t | |||
1453 | index 69c869f..b2d374f 100644 | |||
1454 | --- a/t/issue_67.t | |||
1455 | +++ b/t/issue_67.t | |||
1456 | @@ -77,11 +77,11 @@ sub when { | |||
1457 | 77 | 77 | ||
1458 | 78 | # Disabling the defaults since it conflicts with a running instance. | 78 | # Disabling the defaults since it conflicts with a running instance. |
1459 | 79 | # when('no arguments', '', 11211, 11211); | 79 | # when('no arguments', '', 11211, 11211); |
1461 | 80 | when('specifying tcp port', '-p 11212', 11212, 11212); | 80 | when('specifying tcp port', '-p 11212', 11212, -1); |
1462 | 81 | when('specifying udp port', '-U 11222', 11222, 11222); | 81 | when('specifying udp port', '-U 11222', 11222, 11222); |
1463 | 82 | when('specifying tcp ephemeral port', '-p -1', 0, 0); | 82 | when('specifying tcp ephemeral port', '-p -1', 0, 0); |
1464 | 83 | when('specifying udp ephemeral port', '-U -1', 0, 0); | 83 | when('specifying udp ephemeral port', '-U -1', 0, 0); |
1466 | 84 | when('tcp port disabled', '-p 0', -1, 11211); | 84 | when('tcp port disabled', '-p 0', -1, -1); |
1467 | 85 | when('udp port disabled', '-U 0', 11211, -1); | 85 | when('udp port disabled', '-U 0', 11211, -1); |
1468 | 86 | when('specifying tcp and udp ports', '-p 11232 -U 11233', 11232, 11233); | 86 | when('specifying tcp and udp ports', '-p 11232 -U 11233', 11232, 11233); |
1469 | 87 | when('specifying tcp and disabling udp', '-p 11242 -U 0', 11242, -1); | 87 | when('specifying tcp and disabling udp', '-p 11242 -U 0', 11242, -1); |
1470 | diff --git a/thread.c b/thread.c | |||
1471 | index df05d5f..d17a387 100644 | |||
1472 | --- a/thread.c | |||
1473 | +++ b/thread.c | |||
1474 | @@ -309,7 +309,16 @@ void accept_new_conns(const bool do_accept) { | |||
1475 | 309 | * Set up a thread's information. | 309 | * Set up a thread's information. |
1476 | 310 | */ | 310 | */ |
1477 | 311 | static void setup_thread(LIBEVENT_THREAD *me) { | 311 | static void setup_thread(LIBEVENT_THREAD *me) { |
1478 | 312 | #if defined(LIBEVENT_VERSION_NUMBER) && LIBEVENT_VERSION_NUMBER >= 0x02000101 | ||
1479 | 313 | struct event_config *ev_config; | ||
1480 | 314 | ev_config = event_config_new(); | ||
1481 | 315 | event_config_set_flag(ev_config, EVENT_BASE_FLAG_NOLOCK); | ||
1482 | 316 | me->base = event_base_new_with_config(ev_config); | ||
1483 | 317 | event_config_free(ev_config); | ||
1484 | 318 | #else | ||
1485 | 312 | me->base = event_init(); | 319 | me->base = event_init(); |
1486 | 320 | #endif | ||
1487 | 321 | |||
1488 | 313 | if (! me->base) { | 322 | if (! me->base) { |
1489 | 314 | fprintf(stderr, "Can't allocate event base\n"); | 323 | fprintf(stderr, "Can't allocate event base\n"); |
1490 | 315 | exit(1); | 324 | exit(1); |
1491 | @@ -374,6 +383,8 @@ static void *worker_libevent(void *arg) { | |||
1492 | 374 | register_thread_initialized(); | 383 | register_thread_initialized(); |
1493 | 375 | 384 | ||
1494 | 376 | event_base_loop(me->base, 0); | 385 | event_base_loop(me->base, 0); |
1495 | 386 | |||
1496 | 387 | event_base_free(me->base); | ||
1497 | 377 | return NULL; | 388 | return NULL; |
1498 | 378 | } | 389 | } |
1499 | 379 | 390 | ||
1500 | diff --git a/timedrun.c b/timedrun.c | |||
1501 | index 6d7afb3..6888453 100644 | |||
1502 | --- a/timedrun.c | |||
1503 | +++ b/timedrun.c | |||
1504 | @@ -17,7 +17,7 @@ static void caught_signal(int which) | |||
1505 | 17 | static int wait_for_process(pid_t pid) | 17 | static int wait_for_process(pid_t pid) |
1506 | 18 | { | 18 | { |
1507 | 19 | int rv = EX_SOFTWARE; | 19 | int rv = EX_SOFTWARE; |
1509 | 20 | int stats = 0; | 20 | int status = 0; |
1510 | 21 | int i = 0; | 21 | int i = 0; |
1511 | 22 | struct sigaction sig_handler; | 22 | struct sigaction sig_handler; |
1512 | 23 | 23 | ||
1513 | @@ -32,12 +32,12 @@ static int wait_for_process(pid_t pid) | |||
1514 | 32 | 32 | ||
1515 | 33 | /* Loop forever waiting for the process to quit */ | 33 | /* Loop forever waiting for the process to quit */ |
1516 | 34 | for (i = 0; ;i++) { | 34 | for (i = 0; ;i++) { |
1518 | 35 | pid_t p = waitpid(pid, &stats, 0); | 35 | pid_t p = waitpid(pid, &status, 0); |
1519 | 36 | if (p == pid) { | 36 | if (p == pid) { |
1520 | 37 | /* child exited. Let's get out of here */ | 37 | /* child exited. Let's get out of here */ |
1524 | 38 | rv = WIFEXITED(stats) ? | 38 | rv = WIFEXITED(status) ? |
1525 | 39 | WEXITSTATUS(stats) : | 39 | WEXITSTATUS(status) : |
1526 | 40 | (0x80 | WTERMSIG(stats)); | 40 | (0x80 | WTERMSIG(status)); |
1527 | 41 | break; | 41 | break; |
1528 | 42 | } else { | 42 | } else { |
1529 | 43 | int sig = 0; | 43 | int sig = 0; |
1530 | diff --git a/trace.h b/trace.h | |||
1531 | index dc792a0..94e585d 100644 | |||
1532 | --- a/trace.h | |||
1533 | +++ b/trace.h | |||
1534 | @@ -4,11 +4,11 @@ | |||
1535 | 4 | #ifdef ENABLE_DTRACE | 4 | #ifdef ENABLE_DTRACE |
1536 | 5 | #include "memcached_dtrace.h" | 5 | #include "memcached_dtrace.h" |
1537 | 6 | #else | 6 | #else |
1539 | 7 | #define MEMCACHED_ASSOC_DELETE(arg0, arg1, arg2) | 7 | #define MEMCACHED_ASSOC_DELETE(arg0, arg1) |
1540 | 8 | #define MEMCACHED_ASSOC_DELETE_ENABLED() (0) | 8 | #define MEMCACHED_ASSOC_DELETE_ENABLED() (0) |
1541 | 9 | #define MEMCACHED_ASSOC_FIND(arg0, arg1, arg2) | 9 | #define MEMCACHED_ASSOC_FIND(arg0, arg1, arg2) |
1542 | 10 | #define MEMCACHED_ASSOC_FIND_ENABLED() (0) | 10 | #define MEMCACHED_ASSOC_FIND_ENABLED() (0) |
1544 | 11 | #define MEMCACHED_ASSOC_INSERT(arg0, arg1, arg2) | 11 | #define MEMCACHED_ASSOC_INSERT(arg0, arg1) |
1545 | 12 | #define MEMCACHED_ASSOC_INSERT_ENABLED() (0) | 12 | #define MEMCACHED_ASSOC_INSERT_ENABLED() (0) |
1546 | 13 | #define MEMCACHED_COMMAND_ADD(arg0, arg1, arg2, arg3, arg4) | 13 | #define MEMCACHED_COMMAND_ADD(arg0, arg1, arg2, arg3, arg4) |
1547 | 14 | #define MEMCACHED_COMMAND_ADD_ENABLED() (0) | 14 | #define MEMCACHED_COMMAND_ADD_ENABLED() (0) |
1548 | diff --git a/version.m4 b/version.m4 | |||
1549 | index d763a82..4a02156 100644 | |||
1550 | --- a/version.m4 | |||
1551 | +++ b/version.m4 | |||
1552 | @@ -1 +1 @@ | |||
1554 | 1 | m4_define([VERSION_NUMBER], [1.5.4]) | 1 | m4_define([VERSION_NUMBER], [1.5.6]) |
available in ppa:racb/ experimental