Merge ~racb/ubuntu/+source/memcached:upstream-bump-1.5.6 into ubuntu/+source/memcached:ubuntu/devel

Proposed by Robie Basak
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)
Reviewer Review Type Date Requested Status
Christian Ehrhardt  (community) Approve
Canonical Server Pending
Review via email: mp+341340@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

available in ppa:racb/experimental

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

1. verified the upstream delta between version - ok

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

2. is it really a bugfix release - ok
https://github.com/memcached/memcached/wiki/ReleaseNotes155 - ok
https://github.com/memcached/memcached/wiki/ReleaseNotes156 - special cases
  - 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.

Revision history for this message
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.

review: Needs Information
Revision history for this message
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.

Revision history for this message
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.

Revision history for this message
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.

Revision history for this message
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.

Revision history for this message
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)

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

7. ran the 11 tests of qa-regression-testing
   One fail, but that it had with the former version as well.

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

Thanks for the explanations on the changelog structure btw.

Overall this LGTM +1.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/assoc.c b/assoc.c
index 8cdf581..8e7a810 100644
--- a/assoc.c
+++ b/assoc.c
@@ -27,7 +27,6 @@
2727
28static pthread_cond_t maintenance_cond = PTHREAD_COND_INITIALIZER;28static pthread_cond_t maintenance_cond = PTHREAD_COND_INITIALIZER;
29static pthread_mutex_t maintenance_lock = PTHREAD_MUTEX_INITIALIZER;29static pthread_mutex_t maintenance_lock = PTHREAD_MUTEX_INITIALIZER;
30static pthread_mutex_t hash_items_counter_lock = PTHREAD_MUTEX_INITIALIZER;
3130
32typedef unsigned long int ub4; /* unsigned 4-byte quantities */31typedef unsigned long int ub4; /* unsigned 4-byte quantities */
33typedef unsigned char ub1; /* unsigned 1-byte quantities */32typedef unsigned char ub1; /* unsigned 1-byte quantities */
@@ -47,9 +46,6 @@ static item** primary_hashtable = 0;
47 */46 */
48static item** old_hashtable = 0;47static item** old_hashtable = 0;
4948
50/* Number of items in the hash table. */
51static unsigned int hash_items = 0;
52
53/* Flag: Are we in the middle of expanding now? */49/* Flag: Are we in the middle of expanding now? */
54static bool expanding = false;50static bool expanding = false;
55static bool started_expanding = false;51static bool started_expanding = false;
@@ -144,12 +140,15 @@ static void assoc_expand(void) {
144 }140 }
145}141}
146142
147static void assoc_start_expand(void) {143void assoc_start_expand(uint64_t curr_items) {
148 if (started_expanding)144 if (started_expanding)
149 return;145 return;
150146
151 started_expanding = true;147 if (curr_items > (hashsize(hashpower) * 3) / 2 &&
152 pthread_cond_signal(&maintenance_cond);148 hashpower < HASHPOWER_MAX) {
149 started_expanding = true;
150 pthread_cond_signal(&maintenance_cond);
151 }
153}152}
154153
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 */
@@ -168,15 +167,7 @@ int assoc_insert(item *it, const uint32_t hv) {
168 primary_hashtable[hv & hashmask(hashpower)] = it;167 primary_hashtable[hv & hashmask(hashpower)] = it;
169 }168 }
170169
171 pthread_mutex_lock(&hash_items_counter_lock);170 MEMCACHED_ASSOC_INSERT(ITEM_key(it), it->nkey);
172 hash_items++;
173 if (! expanding && hash_items > (hashsize(hashpower) * 3) / 2 &&
174 hashpower < HASHPOWER_MAX) {
175 assoc_start_expand();
176 }
177 pthread_mutex_unlock(&hash_items_counter_lock);
178
179 MEMCACHED_ASSOC_INSERT(ITEM_key(it), it->nkey, hash_items);
180 return 1;171 return 1;
181}172}
182173
@@ -185,13 +176,10 @@ void assoc_delete(const char *key, const size_t nkey, const uint32_t hv) {
185176
186 if (*before) {177 if (*before) {
187 item *nxt;178 item *nxt;
188 pthread_mutex_lock(&hash_items_counter_lock);
189 hash_items--;
190 pthread_mutex_unlock(&hash_items_counter_lock);
191 /* The DTrace probe cannot be triggered as the last instruction179 /* The DTrace probe cannot be triggered as the last instruction
192 * due to possible tail-optimization by the compiler180 * due to possible tail-optimization by the compiler
193 */181 */
194 MEMCACHED_ASSOC_DELETE(key, nkey, hash_items);182 MEMCACHED_ASSOC_DELETE(key, nkey);
195 nxt = (*before)->h_next;183 nxt = (*before)->h_next;
196 (*before)->h_next = 0; /* probably pointless, but whatever. */184 (*before)->h_next = 0; /* probably pointless, but whatever. */
197 *before = nxt;185 *before = nxt;
diff --git a/assoc.h b/assoc.h
index dda39a0..fb2c922 100644
--- a/assoc.h
+++ b/assoc.h
@@ -6,5 +6,6 @@ void assoc_delete(const char *key, const size_t nkey, const uint32_t hv);
6void do_assoc_move_next_bucket(void);6void do_assoc_move_next_bucket(void);
7int start_assoc_maintenance_thread(void);7int start_assoc_maintenance_thread(void);
8void stop_assoc_maintenance_thread(void);8void stop_assoc_maintenance_thread(void);
9void assoc_start_expand(uint64_t curr_items);
9extern unsigned int hashpower;10extern unsigned int hashpower;
10extern unsigned int item_lock_hashpower;11extern unsigned int item_lock_hashpower;
diff --git a/configure b/configure
index f1e61ff..e479e60 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
1#! /bin/sh1#! /bin/sh
2# Guess values for system-dependent variables and create Makefiles.2# Guess values for system-dependent variables and create Makefiles.
3# Generated by GNU Autoconf 2.69 for memcached 1.5.4.3# Generated by GNU Autoconf 2.69 for memcached 1.5.6.
4#4#
5# Report bugs to <memcached@googlegroups.com>.5# Report bugs to <memcached@googlegroups.com>.
6#6#
@@ -580,8 +580,8 @@ MAKEFLAGS=
580# Identity of this package.580# Identity of this package.
581PACKAGE_NAME='memcached'581PACKAGE_NAME='memcached'
582PACKAGE_TARNAME='memcached'582PACKAGE_TARNAME='memcached'
583PACKAGE_VERSION='1.5.4'583PACKAGE_VERSION='1.5.6'
584PACKAGE_STRING='memcached 1.5.4'584PACKAGE_STRING='memcached 1.5.6'
585PACKAGE_BUGREPORT='memcached@googlegroups.com'585PACKAGE_BUGREPORT='memcached@googlegroups.com'
586PACKAGE_URL=''586PACKAGE_URL=''
587587
@@ -1320,7 +1320,7 @@ if test "$ac_init_help" = "long"; then
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.
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.
1322 cat <<_ACEOF1322 cat <<_ACEOF
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.
13241324
1325Usage: $0 [OPTION]... [VAR=VALUE]...1325Usage: $0 [OPTION]... [VAR=VALUE]...
13261326
@@ -1391,7 +1391,7 @@ fi
13911391
1392if test -n "$ac_init_help"; then1392if test -n "$ac_init_help"; then
1393 case $ac_init_help in1393 case $ac_init_help in
1394 short | recursive ) echo "Configuration of memcached 1.5.4:";;1394 short | recursive ) echo "Configuration of memcached 1.5.6:";;
1395 esac1395 esac
1396 cat <<\_ACEOF1396 cat <<\_ACEOF
13971397
@@ -1495,7 +1495,7 @@ fi
1495test -n "$ac_init_help" && exit $ac_status1495test -n "$ac_init_help" && exit $ac_status
1496if $ac_init_version; then1496if $ac_init_version; then
1497 cat <<\_ACEOF1497 cat <<\_ACEOF
1498memcached configure 1.5.41498memcached configure 1.5.6
1499generated by GNU Autoconf 2.691499generated by GNU Autoconf 2.69
15001500
1501Copyright (C) 2012 Free Software Foundation, Inc.1501Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1964,7 +1964,7 @@ cat >config.log <<_ACEOF
1964This file contains any messages produced by compilers while1964This file contains any messages produced by compilers while
1965running configure, to aid debugging if configure makes a mistake.1965running configure, to aid debugging if configure makes a mistake.
19661966
1967It was created by memcached $as_me 1.5.4, which was1967It was created by memcached $as_me 1.5.6, which was
1968generated by GNU Autoconf 2.69. Invocation command line was1968generated by GNU Autoconf 2.69. Invocation command line was
19691969
1970 $ $0 $@1970 $ $0 $@
@@ -2899,7 +2899,7 @@ fi
28992899
2900# Define the identity of the package.2900# Define the identity of the package.
2901 PACKAGE='memcached'2901 PACKAGE='memcached'
2902 VERSION='1.5.4'2902 VERSION='1.5.6'
29032903
29042904
2905cat >>confdefs.h <<_ACEOF2905cat >>confdefs.h <<_ACEOF
@@ -7156,7 +7156,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
7156# report actual input values of CONFIG_FILES etc. instead of their7156# report actual input values of CONFIG_FILES etc. instead of their
7157# values after options handling.7157# values after options handling.
7158ac_log="7158ac_log="
7159This file was extended by memcached $as_me 1.5.4, which was7159This file was extended by memcached $as_me 1.5.6, which was
7160generated by GNU Autoconf 2.69. Invocation command line was7160generated by GNU Autoconf 2.69. Invocation command line was
71617161
7162 CONFIG_FILES = $CONFIG_FILES7162 CONFIG_FILES = $CONFIG_FILES
@@ -7222,7 +7222,7 @@ _ACEOF
7222cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=17222cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
7223ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"7223ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
7224ac_cs_version="\\7224ac_cs_version="\\
7225memcached config.status 1.5.47225memcached config.status 1.5.6
7226configured by $0, generated by GNU Autoconf 2.69,7226configured by $0, generated by GNU Autoconf 2.69,
7227 with options \\"\$ac_cs_config\\"7227 with options \\"\$ac_cs_config\\"
72287228
diff --git a/crawler.c b/crawler.c
index 56e967a..9c81bba 100644
--- a/crawler.c
+++ b/crawler.c
@@ -252,8 +252,8 @@ static void crawler_metadump_eval(crawler_module_t *cm, item *it, uint32_t hv, i
252 int total = snprintf(cm->c.cbuf, 4096,252 int total = snprintf(cm->c.cbuf, 4096,
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",
254 keybuf,254 keybuf,
255 (it->exptime == 0) ? -1 : (long)it->exptime + process_started,255 (it->exptime == 0) ? -1 : (long)(it->exptime + process_started),
256 (unsigned long long)it->time + process_started,256 (unsigned long long)(it->time + process_started),
257 (unsigned long long)ITEM_get_cas(it),257 (unsigned long long)ITEM_get_cas(it),
258 (it->it_flags & ITEM_FETCHED) ? "yes" : "no",258 (it->it_flags & ITEM_FETCHED) ? "yes" : "no",
259 ITEM_clsid(it),259 ITEM_clsid(it),
@@ -530,6 +530,9 @@ static int do_lru_crawler_start(uint32_t id, uint32_t remaining) {
530 crawlers[sid].next = 0;530 crawlers[sid].next = 0;
531 crawlers[sid].prev = 0;531 crawlers[sid].prev = 0;
532 crawlers[sid].time = 0;532 crawlers[sid].time = 0;
533 if (remaining == LRU_CRAWLER_CAP_REMAINING) {
534 remaining = do_get_lru_size(sid);
535 }
533 crawlers[sid].remaining = remaining;536 crawlers[sid].remaining = remaining;
534 crawlers[sid].slabs_clsid = sid;537 crawlers[sid].slabs_clsid = sid;
535 crawlers[sid].reclaimed = 0;538 crawlers[sid].reclaimed = 0;
@@ -622,7 +625,7 @@ int lru_crawler_start(uint8_t *ids, uint32_t remaining,
622 * Also only clear the crawlerstats once per sid.625 * Also only clear the crawlerstats once per sid.
623 */626 */
624enum crawler_result_type lru_crawler_crawl(char *slabs, const enum crawler_run_type type,627enum crawler_result_type lru_crawler_crawl(char *slabs, const enum crawler_run_type type,
625 void *c, const int sfd) {628 void *c, const int sfd, unsigned int remaining) {
626 char *b = NULL;629 char *b = NULL;
627 uint32_t sid = 0;630 uint32_t sid = 0;
628 int starts = 0;631 int starts = 0;
@@ -651,8 +654,7 @@ enum crawler_result_type lru_crawler_crawl(char *slabs, const enum crawler_run_t
651 }654 }
652 }655 }
653656
654 starts = lru_crawler_start(tocrawl, settings.lru_crawler_tocrawl,657 starts = lru_crawler_start(tocrawl, remaining, type, NULL, c, sfd);
655 type, NULL, c, sfd);
656 if (starts == -1) {658 if (starts == -1) {
657 return CRAWLER_RUNNING;659 return CRAWLER_RUNNING;
658 } else if (starts == -2) {660 } else if (starts == -2) {
diff --git a/crawler.h b/crawler.h
index e009548..f7ebba2 100644
--- a/crawler.h
+++ b/crawler.h
@@ -1,6 +1,8 @@
1#ifndef CRAWLER_H1#ifndef CRAWLER_H
2#define CRAWLER_H2#define CRAWLER_H
33
4#define LRU_CRAWLER_CAP_REMAINING -1
5
4typedef struct {6typedef struct {
5 uint64_t histo[61];7 uint64_t histo[61];
6 uint64_t ttl_hourplus;8 uint64_t ttl_hourplus;
@@ -28,7 +30,8 @@ enum crawler_result_type {
28int start_item_crawler_thread(void);30int start_item_crawler_thread(void);
29int stop_item_crawler_thread(void);31int stop_item_crawler_thread(void);
30int init_lru_crawler(void *arg);32int init_lru_crawler(void *arg);
31enum crawler_result_type lru_crawler_crawl(char *slabs, enum crawler_run_type, void *c, const int sfd);33enum crawler_result_type lru_crawler_crawl(char *slabs, enum crawler_run_type,
34 void *c, const int sfd, unsigned int remaining);
32int lru_crawler_start(uint8_t *ids, uint32_t remaining,35int lru_crawler_start(uint8_t *ids, uint32_t remaining,
33 const enum crawler_run_type type, void *data,36 const enum crawler_run_type type, void *data,
34 void *c, const int sfd);37 void *c, const int sfd);
diff --git a/debian/changelog b/debian/changelog
index 9914ad2..f1ae7d9 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,13 @@
1memcached (1.5.6-0ubuntu1) bionic; urgency=medium
2
3 * New upstream bugfix release (LP: #1753839).
4 * d/p/disable-udp-by-default.patch: drop (now upstream).
5 * d/p/02_service_wrapper.patch: refresh to remove fuzz.
6 * d/p/restore-systemd-sandboxing: restore sandboxing in memcached.service
7 removed by upstream in 1.5.6 to avoid feature regression (LP: #1755460).
8
9 -- Robie Basak <robie.basak@ubuntu.com> Tue, 13 Mar 2018 09:59:06 +0000
10
1memcached (1.5.4-1ubuntu3) bionic; urgency=medium11memcached (1.5.4-1ubuntu3) bionic; urgency=medium
212
3 * SECURITY UPDATE: disable listening on UDP port by default due to13 * SECURITY UPDATE: disable listening on UDP port by default due to
diff --git a/debian/patches/02_service_wrapper.patch b/debian/patches/02_service_wrapper.patch
index a81bd06..355e194 100644
--- a/debian/patches/02_service_wrapper.patch
+++ b/debian/patches/02_service_wrapper.patch
@@ -7,10 +7,8 @@ Description: Additions for service unit file
7Last-Update: 2017-09-137Last-Update: 2017-09-13
8Forwarded: not-needed8Forwarded: not-needed
99
10Index: memcached/scripts/memcached.service10--- a/scripts/memcached.service
11===================================================================11+++ b/scripts/memcached.service
12--- memcached.orig/scripts/memcached.service
13+++ memcached/scripts/memcached.service
14@@ -12,10 +12,10 @@12@@ -12,10 +12,10 @@
15 [Unit]13 [Unit]
16 Description=memcached daemon14 Description=memcached daemon
@@ -22,11 +20,11 @@ Index: memcached/scripts/memcached.service
22-ExecStart=/usr/bin/memcached -p ${PORT} -u ${USER} -m ${CACHESIZE} -c ${MAXCONN} $OPTIONS20-ExecStart=/usr/bin/memcached -p ${PORT} -u ${USER} -m ${CACHESIZE} -c ${MAXCONN} $OPTIONS
23+ExecStart=/usr/share/memcached/scripts/systemd-memcached-wrapper /etc/memcached.conf21+ExecStart=/usr/share/memcached/scripts/systemd-memcached-wrapper /etc/memcached.conf
24 22
25 # Set up a new file system namespace and mounts private /tmp and /var/tmp directories23 # Set up a new file system namespace and mounts private /tmp and /var/tmp
26 # so this service cannot access the global directories and other processes cannot24 # directories so this service cannot access the global directories and
27@@ -68,5 +68,10 @@ RestrictAddressFamilies=AF_INET AF_INET625@@ -80,5 +80,10 @@
28 # Takes away the ability to create or manage any kind of namespace26 # Takes away the ability to create or manage any kind of namespace
29 RestrictNamespaces=true27 ##safer##RestrictNamespaces=true
30 28
31+PIDFile=/var/run/memcached/memcached.pid29+PIDFile=/var/run/memcached/memcached.pid
32+30+
diff --git a/debian/patches/disable-udp-by-default.patch b/debian/patches/disable-udp-by-default.patch
33deleted file mode 10064431deleted file mode 100644
index 7ca2d13..0000000
--- a/debian/patches/disable-udp-by-default.patch
+++ /dev/null
@@ -1,64 +0,0 @@
1From dbb7a8af90054bf4ef51f5814ef7ceb17d83d974 Mon Sep 17 00:00:00 2001
2From: dormando <dormando@rydia.net>
3Date: Tue, 27 Feb 2018 10:50:45 -0800
4Subject: [PATCH] disable UDP port by default
5
6As reported, UDP amplification attacks have started to use insecure
7internet-exposed memcached instances. UDP used to be a lot more popular as a
8transport for memcached many years ago, but I'm not aware of many recent
9users.
10
11Ten years ago, the TCP connection overhead from many clients was relatively
12high (dozens or hundreds per client server), but these days many clients are
13batched, or user fewer processes, or simply anre't worried about it.
14
15While changing the default to listen on localhost only would also help, the
16true culprit is UDP. There are many more use cases for using memcached over
17the network than there are for using the UDP protocol.
18---
19 memcached.c | 6 ++----
20 t/issue_67.t | 4 ++--
21 2 files changed, 4 insertions(+), 6 deletions(-)
22
23diff --git a/memcached.c b/memcached.c
24index 88a5f2ebe..7178666e2 100644
25--- a/memcached.c
26+++ b/memcached.c
27@@ -222,7 +222,7 @@ static void settings_init(void) {
28 settings.use_cas = true;
29 settings.access = 0700;
30 settings.port = 11211;
31- settings.udpport = 11211;
32+ settings.udpport = 0;
33 /* By default this string should be NULL for getaddrinfo() */
34 settings.inter = NULL;
35 settings.maxbytes = 64 * 1024 * 1024; /* default is 64MB */
36@@ -7479,9 +7479,7 @@ int main (int argc, char **argv) {
37 }
38 }
39
40- if (tcp_specified && settings.port != 0 && !udp_specified) {
41- settings.udpport = settings.port;
42- } else if (udp_specified && settings.udpport != 0 && !tcp_specified) {
43+ if (udp_specified && settings.udpport != 0 && !tcp_specified) {
44 settings.port = settings.udpport;
45 }
46
47diff --git a/t/issue_67.t b/t/issue_67.t
48index 69c869f4c..b2d374fa5 100644
49--- a/t/issue_67.t
50+++ b/t/issue_67.t
51@@ -77,11 +77,11 @@ sub when {
52
53 # Disabling the defaults since it conflicts with a running instance.
54 # when('no arguments', '', 11211, 11211);
55-when('specifying tcp port', '-p 11212', 11212, 11212);
56+when('specifying tcp port', '-p 11212', 11212, -1);
57 when('specifying udp port', '-U 11222', 11222, 11222);
58 when('specifying tcp ephemeral port', '-p -1', 0, 0);
59 when('specifying udp ephemeral port', '-U -1', 0, 0);
60-when('tcp port disabled', '-p 0', -1, 11211);
61+when('tcp port disabled', '-p 0', -1, -1);
62 when('udp port disabled', '-U 0', 11211, -1);
63 when('specifying tcp and udp ports', '-p 11232 -U 11233', 11232, 11233);
64 when('specifying tcp and disabling udp', '-p 11242 -U 0', 11242, -1);
diff --git a/debian/patches/restore-systemd-sandboxing b/debian/patches/restore-systemd-sandboxing
65new file mode 1006440new file mode 100644
index 0000000..584e774
--- /dev/null
+++ b/debian/patches/restore-systemd-sandboxing
@@ -0,0 +1,61 @@
1Author: Robie Basak <robie.basak@canonical.com>
2Description: Restore systemd sandboxing
3 Upstream regressed systemd sandboxing for everyone by default because RHEL
4 cannot support it. Put it back again to avoid this functional regression.
5Bug: https://github.com/memcached/memcached/issues/359
6Bug-Ubuntu: https://bugs.launchpad.net/memcached/+bug/1755460
7Forwarded: not-needed
8Last-Update: 2018-03-13
9
10--- a/scripts/memcached.service
11+++ b/scripts/memcached.service
12@@ -42,21 +42,16 @@
13 # of this unit. Protects against vulnerabilities such as CVE-2016-8655
14 RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
15
16-
17-# Some security features are not in the older versions of systemd used by
18-# e.g. RHEL7/CentOS 7. The below settings are automatically edited at package
19-# build time to uncomment them if the target platform supports them.
20-
21 # Attempts to create memory mappings that are writable and executable at
22 # the same time, or to change existing memory mappings to become executable
23 # are prohibited.
24-##safer##MemoryDenyWriteExecute=true
25+MemoryDenyWriteExecute=true
26
27 # Explicit module loading will be denied. This allows to turn off module
28 # load and unload operations on modular kernels. It is recommended to turn
29 # this on for most services that do not need special file systems or extra
30 # kernel modules to work.
31-##safer##ProtectKernelModules=true
32+ProtectKernelModules=true
33
34 # Kernel variables accessible through /proc/sys, /sys, /proc/sysrq-trigger,
35 # /proc/latency_stats, /proc/acpi, /proc/timer_stats, /proc/fs and /proc/irq
36@@ -64,21 +59,21 @@
37 # kernel variables should only be written at boot-time, with the sysctl.d(5)
38 # mechanism. Almost no services need to write to these at runtime; it is hence
39 # recommended to turn this on for most services.
40-##safer##ProtectKernelTunables=true
41+ProtectKernelTunables=true
42
43 # The Linux Control Groups (cgroups(7)) hierarchies accessible through
44 # /sys/fs/cgroup will be made read-only to all processes of the unit.
45 # Except for container managers no services should require write access
46 # to the control groups hierarchies; it is hence recommended to turn this
47 # on for most services
48-##safer##ProtectControlGroups=true
49+ProtectControlGroups=true
50
51 # Any attempts to enable realtime scheduling in a process of the unit are
52 # refused.
53-##safer##RestrictRealtime=true
54+RestrictRealtime=true
55
56 # Takes away the ability to create or manage any kind of namespace
57-##safer##RestrictNamespaces=true
58+RestrictNamespaces=true
59
60 PIDFile=/var/run/memcached/memcached.pid
61
diff --git a/debian/patches/series b/debian/patches/series
index 4e08bec..bb9c45b 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -5,4 +5,4 @@
5fix-distribution.patch5fix-distribution.patch
6always_enable_alignment.patch6always_enable_alignment.patch
7disable_watcher_test.patch7disable_watcher_test.patch
8disable-udp-by-default.patch8restore-systemd-sandboxing
diff --git a/debian/rules b/debian/rules
index ccd01ec..9fc8d04 100755
--- a/debian/rules
+++ b/debian/rules
@@ -26,6 +26,8 @@ override_dh_auto_install:
26 $(CURDIR)/debian/memcached.init26 $(CURDIR)/debian/memcached.init
27 install -m 755 $(CURDIR)/scripts/memcached.service \27 install -m 755 $(CURDIR)/scripts/memcached.service \
28 $(CURDIR)/debian/memcached.service28 $(CURDIR)/debian/memcached.service
29 # Check for LP: #1755460
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
29 install -m 755 $(CURDIR)/scripts/damemtop $(SCRIPTS)31 install -m 755 $(CURDIR)/scripts/damemtop $(SCRIPTS)
30 install -m 644 $(CURDIR)/scripts/damemtop.yaml $(SCRIPTS)32 install -m 644 $(CURDIR)/scripts/damemtop.yaml $(SCRIPTS)
31 install -m 644 $(CURDIR)/scripts/README.damemtop $(SCRIPTS)33 install -m 644 $(CURDIR)/scripts/README.damemtop $(SCRIPTS)
diff --git a/doc/Makefile b/doc/Makefile
index 881c525..0337680 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -191,10 +191,10 @@ OBJEXT = o
191PACKAGE = memcached191PACKAGE = memcached
192PACKAGE_BUGREPORT = memcached@googlegroups.com192PACKAGE_BUGREPORT = memcached@googlegroups.com
193PACKAGE_NAME = memcached193PACKAGE_NAME = memcached
194PACKAGE_STRING = memcached 1.5.4194PACKAGE_STRING = memcached 1.5.6
195PACKAGE_TARNAME = memcached195PACKAGE_TARNAME = memcached
196PACKAGE_URL = 196PACKAGE_URL =
197PACKAGE_VERSION = 1.5.4197PACKAGE_VERSION = 1.5.6
198PATH_SEPARATOR = :198PATH_SEPARATOR = :
199PROFILER = /usr/bin/gcov199PROFILER = /usr/bin/gcov
200PROFILER_FLAGS = -fprofile-arcs -ftest-coverage200PROFILER_FLAGS = -fprofile-arcs -ftest-coverage
@@ -202,7 +202,7 @@ PROFILER_LDFLAGS = -lgcov
202SET_MAKE = 202SET_MAKE =
203SHELL = /bin/bash203SHELL = /bin/bash
204STRIP = 204STRIP =
205VERSION = 1.5.4205VERSION = 1.5.6
206XML2RFC = /usr/bin/xml2rfc206XML2RFC = /usr/bin/xml2rfc
207XSLTPROC = no207XSLTPROC = no
208abs_builddir = /home/dormando/d/p/danga/git/memcached/doc208abs_builddir = /home/dormando/d/p/danga/git/memcached/doc
diff --git a/items.c b/items.c
index 400048b..0aefaf0 100644
--- a/items.c
+++ b/items.c
@@ -138,6 +138,11 @@ static unsigned int temp_lru_size(int slabs_clsid) {
138 return ret;138 return ret;
139}139}
140140
141/* must be locked before call */
142unsigned int do_get_lru_size(uint32_t id) {
143 return sizes[id];
144}
145
141/* Enable this for reference-count debugging. */146/* Enable this for reference-count debugging. */
142#if 0147#if 0
143# define DEBUG_REFCNT(it,op) \148# define DEBUG_REFCNT(it,op) \
@@ -925,7 +930,7 @@ void item_stats_sizes(ADD_STAT add_stats, void *c) {
925 int i;930 int i;
926 for (i = 0; i < stats_sizes_buckets; i++) {931 for (i = 0; i < stats_sizes_buckets; i++) {
927 if (stats_sizes_hist[i] != 0) {932 if (stats_sizes_hist[i] != 0) {
928 char key[8];933 char key[12];
929 snprintf(key, sizeof(key), "%d", i * 32);934 snprintf(key, sizeof(key), "%d", i * 32);
930 APPEND_STAT(key, "%u", stats_sizes_hist[i]);935 APPEND_STAT(key, "%u", stats_sizes_hist[i]);
931 }936 }
diff --git a/items.h b/items.h
index bf126d7..3b99c66 100644
--- a/items.h
+++ b/items.h
@@ -25,6 +25,7 @@ void do_item_update_nolock(item *it);
25int do_item_replace(item *it, item *new_it, const uint32_t hv);25int do_item_replace(item *it, item *new_it, const uint32_t hv);
2626
27int item_is_flushed(item *it);27int item_is_flushed(item *it);
28unsigned int do_get_lru_size(uint32_t id);
2829
29void do_item_linktail_q(item *it);30void do_item_linktail_q(item *it);
30void do_item_unlinktail_q(item *it);31void do_item_unlinktail_q(item *it);
diff --git a/memcached.c b/memcached.c
index a8a724c..7178666 100644
--- a/memcached.c
+++ b/memcached.c
@@ -222,7 +222,7 @@ static void settings_init(void) {
222 settings.use_cas = true;222 settings.use_cas = true;
223 settings.access = 0700;223 settings.access = 0700;
224 settings.port = 11211;224 settings.port = 11211;
225 settings.udpport = 11211;225 settings.udpport = 0;
226 /* By default this string should be NULL for getaddrinfo() */226 /* By default this string should be NULL for getaddrinfo() */
227 settings.inter = NULL;227 settings.inter = NULL;
228 settings.maxbytes = 64 * 1024 * 1024; /* default is 64MB */228 settings.maxbytes = 64 * 1024 * 1024; /* default is 64MB */
@@ -3338,7 +3338,7 @@ static void process_stats_conns(ADD_STAT add_stats, void *c) {
3338 int i;3338 int i;
3339 char key_str[STAT_KEY_LEN];3339 char key_str[STAT_KEY_LEN];
3340 char val_str[STAT_VAL_LEN];3340 char val_str[STAT_VAL_LEN];
3341 char conn_name[MAXPATHLEN + sizeof("unix:")];3341 char conn_name[MAXPATHLEN + sizeof("unix:") + sizeof("65535")];
3342 int klen = 0, vlen = 0;3342 int klen = 0, vlen = 0;
33433343
3344 assert(add_stats);3344 assert(add_stats);
@@ -4525,7 +4525,7 @@ static void process_lru_command(conn *c, token_t *tokens, const size_t ntokens)
4525static void process_extstore_command(conn *c, token_t *tokens, const size_t ntokens) {4525static void process_extstore_command(conn *c, token_t *tokens, const size_t ntokens) {
4526 set_noreply_maybe(c, tokens, ntokens);4526 set_noreply_maybe(c, tokens, ntokens);
4527 bool ok = true;4527 bool ok = true;
4528 if (ntokens < 3) {4528 if (ntokens < 4) {
4529 ok = false;4529 ok = false;
4530 } else if (strcmp(tokens[1].value, "free_memchunks") == 0 && ntokens > 4) {4530 } else if (strcmp(tokens[1].value, "free_memchunks") == 0 && ntokens > 4) {
4531 /* per-slab-class free chunk setting. */4531 /* per-slab-class free chunk setting. */
@@ -4770,7 +4770,8 @@ static void process_command(conn *c, char *command) {
4770 return;4770 return;
4771 }4771 }
47724772
4773 rv = lru_crawler_crawl(tokens[2].value, CRAWLER_EXPIRED, NULL, 0);4773 rv = lru_crawler_crawl(tokens[2].value, CRAWLER_EXPIRED, NULL, 0,
4774 settings.lru_crawler_tocrawl);
4774 switch(rv) {4775 switch(rv) {
4775 case CRAWLER_OK:4776 case CRAWLER_OK:
4776 out_string(c, "OK");4777 out_string(c, "OK");
@@ -4800,7 +4801,7 @@ static void process_command(conn *c, char *command) {
4800 }4801 }
48014802
4802 int rv = lru_crawler_crawl(tokens[2].value, CRAWLER_METADUMP,4803 int rv = lru_crawler_crawl(tokens[2].value, CRAWLER_METADUMP,
4803 c, c->sfd);4804 c, c->sfd, LRU_CRAWLER_CAP_REMAINING);
4804 switch(rv) {4805 switch(rv) {
4805 case CRAWLER_OK:4806 case CRAWLER_OK:
4806 out_string(c, "OK");4807 out_string(c, "OK");
@@ -5973,6 +5974,7 @@ static int server_sockets(int port, enum network_transport transport,
5973 char *e = strchr(p, ']');5974 char *e = strchr(p, ']');
5974 if (e == NULL) {5975 if (e == NULL) {
5975 fprintf(stderr, "Invalid IPV6 address: \"%s\"", p);5976 fprintf(stderr, "Invalid IPV6 address: \"%s\"", p);
5977 free(list);
5976 return 1;5978 return 1;
5977 }5979 }
5978 h = ++p; // skip the opening '['5980 h = ++p; // skip the opening '['
@@ -5991,6 +5993,7 @@ static int server_sockets(int port, enum network_transport transport,
5991 ++s;5993 ++s;
5992 if (!safe_strtol(s, &the_port)) {5994 if (!safe_strtol(s, &the_port)) {
5993 fprintf(stderr, "Invalid port number: \"%s\"", s);5995 fprintf(stderr, "Invalid port number: \"%s\"", s);
5996 free(list);
5994 return 1;5997 return 1;
5995 }5998 }
5996 }5999 }
@@ -6126,6 +6129,10 @@ static void clock_handler(const int fd, const short which, void *arg) {
6126#endif6129#endif
6127 }6130 }
61286131
6132 // While we're here, check for hash table expansion.
6133 // This function should be quick to avoid delaying the timer.
6134 assoc_start_expand(stats_state.curr_items);
6135
6129 evtimer_set(&clockevent, clock_handler, 0);6136 evtimer_set(&clockevent, clock_handler, 0);
6130 event_base_set(main_base, &clockevent);6137 event_base_set(main_base, &clockevent);
6131 evtimer_add(&clockevent, &t);6138 evtimer_add(&clockevent, &t);
@@ -7472,9 +7479,7 @@ int main (int argc, char **argv) {
7472 }7479 }
7473 }7480 }
74747481
7475 if (tcp_specified && settings.port != 0 && !udp_specified) {7482 if (udp_specified && settings.udpport != 0 && !tcp_specified) {
7476 settings.udpport = settings.port;
7477 } else if (udp_specified && settings.udpport != 0 && !tcp_specified) {
7478 settings.port = settings.udpport;7483 settings.port = settings.udpport;
7479 }7484 }
74807485
@@ -7568,7 +7573,17 @@ int main (int argc, char **argv) {
7568 }7573 }
75697574
7570 /* initialize main thread libevent instance */7575 /* initialize main thread libevent instance */
7576#if defined(LIBEVENT_VERSION_NUMBER) && LIBEVENT_VERSION_NUMBER >= 0x02000101
7577 /* If libevent version is larger/equal to 2.0.2-alpha, use newer version */
7578 struct event_config *ev_config;
7579 ev_config = event_config_new();
7580 event_config_set_flag(ev_config, EVENT_BASE_FLAG_NOLOCK);
7581 main_base = event_base_new_with_config(ev_config);
7582 event_config_free(ev_config);
7583#else
7584 /* Otherwise, use older API */
7571 main_base = event_init();7585 main_base = event_init();
7586#endif
75727587
7573 /* initialize other stuff */7588 /* initialize other stuff */
7574 logger_init();7589 logger_init();
@@ -7710,8 +7725,9 @@ int main (int argc, char **argv) {
7710 if (portnumber_file) {7725 if (portnumber_file) {
7711 fclose(portnumber_file);7726 fclose(portnumber_file);
7712 rename(temp_portnumber_filename, portnumber_filename);7727 rename(temp_portnumber_filename, portnumber_filename);
7713 free(temp_portnumber_filename);
7714 }7728 }
7729 if (temp_portnumber_filename)
7730 free(temp_portnumber_filename);
7715 }7731 }
77167732
7717 /* Give the sockets a moment to open. I know this is dumb, but the error7733 /* Give the sockets a moment to open. I know this is dumb, but the error
@@ -7753,5 +7769,8 @@ int main (int argc, char **argv) {
7753 if (u_socket)7769 if (u_socket)
7754 free(u_socket);7770 free(u_socket);
77557771
7772 /* cleanup base */
7773 event_base_free(main_base);
7774
7756 return retval;7775 return retval;
7757}7776}
diff --git a/memcached.spec b/memcached.spec
index a149db3..697c38f 100644
--- a/memcached.spec
+++ b/memcached.spec
@@ -1,21 +1,48 @@
1# Set with_systemd on distros that use it, so we can install the service
2# file, otherwise the sysvinit script will be installed
3%if 0%{?fedora} >= 14 || 0%{?rhel} >= 7 || 0%{?suse_version} >= 1210
4%global with_systemd 1
5BuildRequires: systemd-units
6
7# Disable some systemd safety features on OSes without a new enough systemd
8# (new enough is systemd >= 233)
9%if 0%{?fedora} < 26 || 0%{?rhel} > 0
10%global safer_systemd 0
11%else
12%global safer_systemd 1
13%endif
14
15%else
16%global with_systemd 0
17%endif
18
1Name: memcached19Name: memcached
2Version: 1.5.420Version: 1.5.6
3Release: 1%{?dist}21Release: 1%{?dist}
4Summary: High Performance, Distributed Memory Object Cache22Summary: High Performance, Distributed Memory Object Cache
523
6Group: System Environment/Daemons24Group: System Environment/Daemons
7License: BSD25License: BSD
8URL: http://memcached.org26URL: http://memcached.org
9Source0: http://memcached.org/files/%{name}-1.5.4.tar.gz27Source0: http://memcached.org/files/%{name}-%{version}.tar.gz
28Source1: memcached.sysconfig
29Source2: memcached.service
30Source3: memcached@.service
10BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)31BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
1132
12BuildRequires: libevent-devel33BuildRequires: libevent-devel
13BuildRequires: perl(Test::More)34BuildRequires: perl(Test::More)
14BuildRequires: /usr/bin/prove35BuildRequires: /usr/bin/prove
15Requires: initscripts36Requires: initscripts
37%if %{with_systemd}
38Requires(post): systemd-units
39Requires(preun): systemd-units
40Requires(postun): systemd-units
41%else
16Requires(post): /sbin/chkconfig42Requires(post): /sbin/chkconfig
17Requires(preun): /sbin/chkconfig, /sbin/service43Requires(preun): /sbin/chkconfig, /sbin/service
18Requires(postun): /sbin/service44Requires(postun): /sbin/service
45%endif
1946
20%description47%description
21memcached is a high-performance, distributed memory object caching48memcached is a high-performance, distributed memory object caching
@@ -23,7 +50,7 @@ system, generic in nature, but intended for use in speeding up dynamic
23web applications by alleviating database load.50web applications by alleviating database load.
2451
25%prep52%prep
26%setup -q -n %{name}-1.5.453%setup -q -n %{name}-%{version}
2754
2855
29%build56%build
@@ -31,53 +58,90 @@ web applications by alleviating database load.
3158
32make %{?_smp_mflags}59make %{?_smp_mflags}
3360
61
34%check62%check
35make test63make test
3664
65
37%install66%install
38rm -rf %{buildroot}67rm -rf %{buildroot}
39make install DESTDIR=%{buildroot}68make install DESTDIR=%{buildroot}
4069
41# remove memcached-debug70# remove memcached-debug
42rm -f %{buildroot}/%{_bindir}/memcached-debug71rm -f %{buildroot}/%{_bindir}/%{name}-debug
4372
44# Perl script for monitoring memcached73# Perl script for monitoring memcached
45install -Dp -m0755 scripts/memcached-tool %{buildroot}%{_bindir}/memcached-tool74install -Dp -m0755 scripts/memcached-tool %{buildroot}%{_bindir}/%{name}-tool
4675
47# Init script76# Init script
48install -Dp -m0755 scripts/memcached.sysv %{buildroot}%{_initrddir}/memcached77%if %{with_systemd}
78install -Dp -m0755 scripts/memcached.service %{buildroot}%{_unitdir}/%{name}.service
79install -Dp -m0755 scripts/memcached@.service %{buildroot}%{_unitdir}/%{name}@.service
80
81if [ %{safer_systemd} -gt 0 ]; then
82 sed -e -i 's/^##safer##//g' %{buildroot}%{_unitdir}/%{name}.service %{buildroot}%{_unitdir}/%{name}@.service
83else
84 sed -e -i 's/^##safer##/#/g' %{buildroot}%{_unitdir}/%{name}.service %{buildroot}%{_unitdir}/%{name}@.service
85fi
86%else
87install -Dp -m0755 scripts/memcached.sysv %{buildroot}%{_initrddir}/%{name}
88%endif
4989
50# Default configs90# Default configs
51mkdir -p %{buildroot}/%{_sysconfdir}/sysconfig91install -Dp -m0644 scripts/memcached.sysconfig %{buildroot}%{_sysconfdir}/sysconfig/%{name}
52cat <<EOF >%{buildroot}/%{_sysconfdir}/sysconfig/%{name}
53PORT="11211"
54USER="nobody"
55MAXCONN="1024"
56CACHESIZE="64"
57OPTIONS=""
58EOF
5992
60# pid directory93# pid directory
61mkdir -p %{buildroot}/%{_localstatedir}/run/memcached94mkdir -p %{buildroot}/%{_localstatedir}/run/%{name}
95
6296
63%clean97%clean
64rm -rf %{buildroot}98rm -rf %{buildroot}
6599
66100
67%post101%post
68/sbin/chkconfig --add %{name}102if [ $1 -eq 1 ]; then
103 # Initial install
104%if %{with_systemd}
105 /bin/systemctl daemon-reload >/dev/null 2>&1 || :
106%else
107 /sbin/chkconfig --add %{name}
108%endif
109fi
110
69111
70%preun112%preun
71if [ "$1" = 0 ] ; then113if [ "$1" = 0 ] ; then
72 /sbin/service %{name} stop > /dev/null 2>&1114 # Removal, not upgrade
115%if %{with_systemd}
116 /bin/systemctl --no-reload disable %{name}.service > /dev/null 2>&1 || :
117 /bin/systemctl --no-reload disable %{name}@\*.service > /dev/null 2>&1 || :
118 /bin/systemctl stop %{name}.service > /dev/null 2>&1 || :
119 /bin/systemctl stop %{name}@\*.service > /dev/null 2>&1 || :
120%else
121 /sbin/service %{name} stop > /dev/null 2&>1 || :
73 /sbin/chkconfig --del %{name}122 /sbin/chkconfig --del %{name}
123%endif
74fi124fi
125
75exit 0126exit 0
76127
128
77%postun129%postun
78if [ "$1" -ge 1 ]; then130%if %{with_systemd}
79 /sbin/service %{name} condrestart > /dev/null 2>&1131 /bin/systemctl daemon-reload >/dev/null 2>&1 || :
80fi132%endif
133
134# Don't auto-restart memcached on upgrade -- let user control when cache flushes
135# if [ "$1" -ge 1 ]; then
136# # upgrade, not install
137# %if %{with_systemd}
138# /bin/systemctl try-restart %{name}.service
139# /bin/systemctl try-restart %{name}@\*.service
140# %else
141# /sbin/service %named condrestart 2>/dev/null || :
142# %endif
143#fi
144
81exit 0145exit 0
82146
83147
@@ -86,14 +150,24 @@ exit 0
86%doc AUTHORS ChangeLog COPYING NEWS README.md doc/CONTRIBUTORS doc/*.txt150%doc AUTHORS ChangeLog COPYING NEWS README.md doc/CONTRIBUTORS doc/*.txt
87%config(noreplace) %{_sysconfdir}/sysconfig/%{name}151%config(noreplace) %{_sysconfdir}/sysconfig/%{name}
88152
89%dir %attr(750,nobody,nobody) %{_localstatedir}/run/memcached153%dir %attr(750,nobody,nobody) %{_localstatedir}/run/%{name}
90%{_bindir}/memcached-tool154%{_bindir}/%{name}-tool
91%{_bindir}/memcached155%{_bindir}/%{name}
92%{_mandir}/man1/memcached.1*156%{_mandir}/man1/%{name}.1*
93%{_initrddir}/memcached157%{_includedir}/%{name}
94%{_includedir}/memcached158
159%if %{with_systemd}
160%{_unitdir}/%{name}.service
161%{_unitdir}/%{name}@.service
162%else
163%{_initrddir}/%{name}
164%endif
95165
96%changelog166%changelog
167* Wed Jul 5 2017 J. Grizzard <jg-github@lupine.org> - 1.4.39
168- Add systemd-aware build
169- Add both static and instanced versions of memcached unit files
170
97* Mon Nov 2 2009 Dormando <dormando@rydia.net> - 1.4.3-1171* Mon Nov 2 2009 Dormando <dormando@rydia.net> - 1.4.3-1
98- Fix autogen more.172- Fix autogen more.
99173
@@ -113,7 +187,7 @@ exit 0
113- above suggestions from Bernard Johnson187- above suggestions from Bernard Johnson
114188
115* Mon May 7 2007 Paul Lindner <lindner@inuus.com> - 1.2.2-2189* Mon May 7 2007 Paul Lindner <lindner@inuus.com> - 1.2.2-2
116- Tidiness improvements suggested by Ruben Kerkhof in bugzilla #238994190- Tidyness improvements suggested by Ruben Kerkhof in bugzilla #238994
117191
118* Fri May 4 2007 Paul Lindner <lindner@inuus.com> - 1.2.2-1192* Fri May 4 2007 Paul Lindner <lindner@inuus.com> - 1.2.2-1
119- Initial spec file created via rpmdev-newspec193- Initial spec file created via rpmdev-newspec
diff --git a/memcached_dtrace.d b/memcached_dtrace.d
index 41617ff..3443795 100644
--- a/memcached_dtrace.d
+++ b/memcached_dtrace.d
@@ -111,19 +111,15 @@ provider memcached {
111 * Fired when a new item has been inserted.111 * Fired when a new item has been inserted.
112 * @param key the key just inserted112 * @param key the key just inserted
113 * @param keylen length of the key113 * @param keylen length of the key
114 * @param nokeys the total number of keys currently stored,
115 * including the key for which insert was called.
116 */114 */
117 probe assoc__insert(const char *key, int keylen, int nokeys);115 probe assoc__insert(const char *key, int keylen);
118116
119 /**117 /**
120 * Fired when a new item has been removed.118 * Fired when a new item has been removed.
121 * @param key the key just deleted119 * @param key the key just deleted
122 * @param keylen length of the key120 * @param keylen length of the key
123 * @param nokeys the total number of keys currently stored,
124 * excluding the key for which delete was called.
125 */121 */
126 probe assoc__delete(const char *key, int keylen, int nokeys);122 probe assoc__delete(const char *key, int keylen);
127123
128 /**124 /**
129 * Fired when an item is linked into the cache.125 * Fired when an item is linked into the cache.
diff --git a/scripts/memcached-automove-extstore b/scripts/memcached-automove-extstore
index fa7a11c..db66d8c 100755
--- a/scripts/memcached-automove-extstore
+++ b/scripts/memcached-automove-extstore
@@ -55,17 +55,17 @@ def window_key_check(history, key):
55def determine_move(history, stats, diffs, memfree):55def determine_move(history, stats, diffs, memfree):
56 """ Figure out of a page move is in order.56 """ Figure out of a page move is in order.
5757
58 - we should use as much memory as possible to buffer items, reducing58 - Use as much memory as possible to hold items, reducing the load on
59 the load on flash.59 flash.
60 - tries to keep the global free page pool inbetween poolmin/poolmax.60 - tries to keep the global free page pool inbetween poolmin/poolmax.
61 - avoids flapping as much as possible:61 - avoids flapping as much as possible:
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.
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.
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.
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.
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.
67 - age balancing should move memory around large classes, which then67 - autmover adjusts above limits once per minute based on current sizes.
68 adjusts the per-class free chunk minimums.68 - if youngest is below the age ratio limit of oldest, move a page to it.
69 """69 """
70 # rotate windows70 # rotate windows
71 history['w'].append({})71 history['w'].append({})
@@ -88,6 +88,7 @@ def determine_move(history, stats, diffs, memfree):
88 pool_high = window_key_check(history, 'slab_pool_high')88 pool_high = window_key_check(history, 'slab_pool_high')
89 for sid, slab in diffs.items():89 for sid, slab in diffs.items():
90 small_slab = False90 small_slab = False
91 free_enough = False
91 # Only balance larger slab classes92 # Only balance larger slab classes
92 if slab['chunk_size'] < args.size:93 if slab['chunk_size'] < args.size:
93 small_slab = True94 small_slab = True
@@ -102,7 +103,9 @@ def determine_move(history, stats, diffs, memfree):
102 if slab['evicted_d'] > 0:103 if slab['evicted_d'] > 0:
103 w[sid]['dirty'] = 1104 w[sid]['dirty'] = 1
104 w[sid]['ev'] = 1105 w[sid]['ev'] = 1
105 if slab['free_chunks'] > memfree[sid] and memfree[sid] > 0:106 if slab['free_chunks'] > memfree[sid]:
107 free_enough = True
108 if memfree[sid] > 0 and slab['free_chunks'] > (memfree[sid] * 2):
106 w[sid]['excess_free'] = 1109 w[sid]['excess_free'] = 1
107 w[sid]['age'] = slab['age']110 w[sid]['age'] = slab['age']
108 age = window_check(history, sid, 'age') / len(history['w'])111 age = window_check(history, sid, 'age') / len(history['w'])
@@ -121,24 +124,25 @@ def determine_move(history, stats, diffs, memfree):
121 too_free = True124 too_free = True
122125
123 # are we the oldest slab class? (and a valid target)126 # are we the oldest slab class? (and a valid target)
127 # don't consider for young if we've recently given it unused memory
124 if small_slab == False:128 if small_slab == False:
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:
126 oldest = (sid, age)130 oldest = (sid, age)
127 if age < youngest[1] and slab['total_pages'] > 0 \131 if age < youngest[1] and slab['total_pages'] > 0 \
128 and window_check(history, sid, 'excess_free') < len(history['w']):132 and window_check(history, sid, 'excess_free') < len(history['w']) \
133 and not (window_check(history, sid, 'relaxed') and free_enough):
129 youngest = (sid, age)134 youngest = (sid, age)
130135
131136
132 if w.get('slab_pool_high') and youngest[0] != -1:137 if w.get('slab_pool_high') and youngest[0] != -1:
133 # if global pool is too high, feed youngest large class.138 # if global pool is too high, feed youngest large class.
134 # decision = (0, youngest[0])139 if slab['free_chunks'] <= memfree[youngest[0]]:
135 # No current way to assign directly from global to a class.140 decision = (0, youngest[0])
136 # minimize the free chunks limiter and re-check.141 w[youngest[0]]['relaxed'] = 1
137 decision = (youngest[0], -2)
138 elif too_free == False and pool_low and oldest[0] != -1:142 elif too_free == False and pool_low and oldest[0] != -1:
139 # if pool is too low, take from oldest large class.143 # if pool is too low, take from oldest large class.
140 if args.verbose:144 if args.verbose:
141 print("oldest: [class: {}] [age: {}]".format(int(oldest[0]), oldest[1]))145 print("oldest: [class: {}] [age: {:.2f}]".format(int(oldest[0]), oldest[1]))
142 decision = (oldest[0], 0)146 decision = (oldest[0], 0)
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]:
144 # youngest is outside of the tolerance ratio, move a page around.148 # youngest is outside of the tolerance ratio, move a page around.
@@ -148,8 +152,10 @@ def determine_move(history, stats, diffs, memfree):
148152
149 slab = diffs[youngest[0]]153 slab = diffs[youngest[0]]
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)))
151 if (slab['free_chunks'] <= memfree[youngest[0]]) and (youngest[1] < oldest[1] * args.ratio):155 if youngest[1] < oldest[1] * args.ratio:
152 decision = (oldest[0], youngest[0])156 w[youngest[0]]['relaxed'] = 1
157 if slab['free_chunks'] <= memfree[youngest[0]]:
158 decision = (0, youngest[0])
153159
154 if (len(history['w']) >= args.window):160 if (len(history['w']) >= args.window):
155 return decision161 return decision
@@ -289,27 +295,16 @@ while True:
289 (diffs, totals) = diff_stats(stats_pre, stats_post)295 (diffs, totals) = diff_stats(stats_pre, stats_post)
290 #if args.verbose:296 #if args.verbose:
291 # show_detail(diffs, totals)297 # show_detail(diffs, totals)
292 if (last_memfree_check < time() - 60) and totals.get('total_pages'):
293 memfree = memfree_check(s, diffs, totals)
294 last_memfree_check = time()
295 decision = (-1, -1)
296 if int(stats['evictions']) > 0:298 if int(stats['evictions']) > 0:
299 if (last_memfree_check < time() - 60) and totals.get('total_pages'):
300 memfree = memfree_check(s, diffs, totals)
301 last_memfree_check = time()
302 decision = (-1, -1)
297 decision = determine_move(history, stats, diffs, memfree)303 decision = determine_move(history, stats, diffs, memfree)
298 if int(decision[0]) > 0 and int(decision[1]) >= 0:304 if int(decision[0]) > 0 and int(decision[1]) >= 0:
299 print("moving page from, to:", decision)305 print("moving page from, to:", decision)
300 if args.automove:306 if args.automove:
301 run_move(s, decision)307 run_move(s, decision)
302 elif int(decision[0]) > 0 and decision[1] == -2:
303 # we've been told to zero out the memory limit.
304 # let the memfree check run "soon".
305 # this (purposefully) can slowly remove limits on
306 # multiple classes if global pool stays too high.
307 last_memfree_check = time() - 58
308 s.write("extstore free_memchunks {} {}\r\n".format(decision[0], 0))
309 s.readline()
310 if args.verbose:
311 print("relaxing free:", decision[0])
312
313308
314 # Minimize sleeping if we just moved a page to global pool.309 # Minimize sleeping if we just moved a page to global pool.
315 # Improves responsiveness during flushes/quick changes.310 # Improves responsiveness during flushes/quick changes.
diff --git a/scripts/memcached.service b/scripts/memcached.service
index 2bfbb67..88a4b8a 100644
--- a/scripts/memcached.service
+++ b/scripts/memcached.service
@@ -1,10 +1,10 @@
1# It's not recommended to modify this file in-place, because it will be1# It's not recommended to modify this file in-place, because it will be
2# overwritten during upgrades. If you want to customize, the best2# overwritten during upgrades. If you want to customize, the best
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.
44#
5# For example, to pass additional options, create an override unit5# For example, to pass additional options, create an override unit
6# (as is done by systemctl edit) and enter the following:6# (as is done by systemctl edit) and enter the following:
77#
8# [Service]8# [Service]
9# Environment=OPTIONS="-l 127.0.0.1,::1"9# Environment=OPTIONS="-l 127.0.0.1,::1"
1010
@@ -17,56 +17,68 @@ After=network.target
17EnvironmentFile=/etc/sysconfig/memcached17EnvironmentFile=/etc/sysconfig/memcached
18ExecStart=/usr/bin/memcached -p ${PORT} -u ${USER} -m ${CACHESIZE} -c ${MAXCONN} $OPTIONS18ExecStart=/usr/bin/memcached -p ${PORT} -u ${USER} -m ${CACHESIZE} -c ${MAXCONN} $OPTIONS
1919
20# Set up a new file system namespace and mounts private /tmp and /var/tmp directories20# Set up a new file system namespace and mounts private /tmp and /var/tmp
21# so this service cannot access the global directories and other processes cannot21# directories so this service cannot access the global directories and
22# access this service's directories.22# other processes cannot access this service's directories.
23PrivateTmp=true23PrivateTmp=true
2424
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
26# invoked by this unit.
26ProtectSystem=full27ProtectSystem=full
2728
28# Ensures that the service process and all its children can never gain new privileges29# Ensures that the service process and all its children can never gain new
30# privileges
29NoNewPrivileges=true31NoNewPrivileges=true
3032
31# Sets up a new /dev namespace for the executed processes and only adds API pseudo devices33# Sets up a new /dev namespace for the executed processes and only adds API
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
33# but no physical devices such as /dev/sda.35# the pseudo TTY subsystem) to it, but no physical devices such as /dev/sda.
34PrivateDevices=true36PrivateDevices=true
3537
36# Required for dropping privileges and running as a different user38# Required for dropping privileges and running as a different user
37CapabilityBoundingSet=CAP_SETGID CAP_SETUID CAP_SYS_RESOURCE39CapabilityBoundingSet=CAP_SETGID CAP_SETUID CAP_SYS_RESOURCE
3840
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
40# or to change existing memory mappings to become executable are prohibited.42# of this unit. Protects against vulnerabilities such as CVE-2016-8655
41MemoryDenyWriteExecute=true43RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
4244
43# Explicit module loading will be denied. This allows to turn off module load and unload
44# operations on modular kernels. It is recommended to turn this on for most services that
45# do not need special file systems or extra kernel modules to work.
46ProtectKernelModules=true
4745
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
49# /proc/acpi, /proc/timer_stats, /proc/fs and /proc/irq will be made read-only to all processes47# e.g. RHEL7/CentOS 7. The below settings are automatically edited at package
50# of the unit. Usually, tunable kernel variables should only be written at boot-time, with the48# build time to uncomment them if the target platform supports them.
51# sysctl.d(5) mechanism. Almost no services need to write to these at runtime; it is hence
52# recommended to turn this on for most services.
53ProtectKernelTunables=true
5449
55# The Linux Control Groups (cgroups(7)) hierarchies accessible through /sys/fs/cgroup will be50# Attempts to create memory mappings that are writable and executable at
56# made read-only to all processes of the unit. Except for container managers no services should51# the same time, or to change existing memory mappings to become executable
57# require write access to the control groups hierarchies; it is hence recommended to turn this on52# are prohibited.
58# for most services53##safer##MemoryDenyWriteExecute=true
59ProtectControlGroups=true
6054
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
62RestrictRealtime=true56# load and unload operations on modular kernels. It is recommended to turn
57# this on for most services that do not need special file systems or extra
58# kernel modules to work.
59##safer##ProtectKernelModules=true
6360
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,
65# Protects against vulnerabilities such as CVE-2016-865562# /proc/latency_stats, /proc/acpi, /proc/timer_stats, /proc/fs and /proc/irq
66RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX63# will be made read-only to all processes of the unit. Usually, tunable
64# kernel variables should only be written at boot-time, with the sysctl.d(5)
65# mechanism. Almost no services need to write to these at runtime; it is hence
66# recommended to turn this on for most services.
67##safer##ProtectKernelTunables=true
68
69# The Linux Control Groups (cgroups(7)) hierarchies accessible through
70# /sys/fs/cgroup will be made read-only to all processes of the unit.
71# Except for container managers no services should require write access
72# to the control groups hierarchies; it is hence recommended to turn this
73# on for most services
74##safer##ProtectControlGroups=true
75
76# Any attempts to enable realtime scheduling in a process of the unit are
77# refused.
78##safer##RestrictRealtime=true
6779
68# Takes away the ability to create or manage any kind of namespace80# Takes away the ability to create or manage any kind of namespace
69RestrictNamespaces=true81##safer##RestrictNamespaces=true
7082
71[Install]83[Install]
72WantedBy=multi-user.target84WantedBy=multi-user.target
diff --git a/scripts/memcached.sysconfig b/scripts/memcached.sysconfig
73new file mode 10064485new file mode 100644
index 0000000..bd46483
--- /dev/null
+++ b/scripts/memcached.sysconfig
@@ -0,0 +1,10 @@
1# These defaults will be used by every memcached instance, unless overridden
2# by values in /etc/sysconfig/memcached.<port>
3USER="nobody"
4MAXCONN="1024"
5CACHESIZE="64"
6OPTIONS=""
7
8# The PORT variable will only be used by memcached.service, not by
9# memcached@xxxxx services, which will use the xxxxx
10PORT="11211"
diff --git a/scripts/memcached@.service b/scripts/memcached@.service
0new file mode 10064411new file mode 100644
index 0000000..4e9f1d7
--- /dev/null
+++ b/scripts/memcached@.service
@@ -0,0 +1,89 @@
1# It's not recommended to modify this file in-place, because it will be
2# overwritten during upgrades. If you want to customize, the best
3# way is to use the "systemctl edit" command to create an override unit.
4#
5# For example, to pass additional options, create an override unit
6# (as is done by systemctl edit) and enter the following:
7#
8# [Service]
9# Environment=OPTIONS="-l 127.0.0.1,::1"
10#
11# To use the "instanced" version of this, just start 'memcached@11211' or
12# whatever port you'd like. If /etc/sysconfig/memcached.<port> exists, it
13# will be read first, so you can set different parameters for a given
14# instance.
15
16[Unit]
17Description=memcached daemon
18After=network.target
19
20[Service]
21EnvironmentFile=/etc/sysconfig/memcached
22EnvironmentFile=-/etc/sysconfig/memcached.%i
23ExecStart=/usr/bin/memcached -p %i -u ${USER} -m ${CACHESIZE} -c ${MAXCONN} $OPTIONS
24
25# Set up a new file system namespace and mounts private /tmp and /var/tmp
26# directories so this service cannot access the global directories and
27# other processes cannot access this service's directories.
28PrivateTmp=true
29
30# Mounts the /usr, /boot, and /etc directories read-only for processes
31# invoked by this unit.
32ProtectSystem=full
33
34# Ensures that the service process and all its children can never gain new
35# privileges
36NoNewPrivileges=true
37
38# Sets up a new /dev namespace for the executed processes and only adds API
39# pseudo devices such as /dev/null, /dev/zero or /dev/random (as well as
40# the pseudo TTY subsystem) to it, but no physical devices such as /dev/sda.
41PrivateDevices=true
42
43# Required for dropping privileges and running as a different user
44CapabilityBoundingSet=CAP_SETGID CAP_SETUID CAP_SYS_RESOURCE
45
46# Restricts the set of socket address families accessible to the processes
47# of this unit. Protects against vulnerabilities such as CVE-2016-8655
48RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
49
50
51# Some security features are not in the older versions of systemd used by
52# e.g. RHEL7/CentOS 7. The below settings are automatically edited at package
53# build time to uncomment them if the target platform supports them.
54
55# Attempts to create memory mappings that are writable and executable at
56# the same time, or to change existing memory mappings to become executable
57# are prohibited.
58##safer##MemoryDenyWriteExecute=true
59
60# Explicit module loading will be denied. This allows to turn off module
61# load and unload operations on modular kernels. It is recommended to turn
62# this on for most services that do not need special file systems or extra
63# kernel modules to work.
64##safer##ProtectKernelModules=true
65
66# Kernel variables accessible through /proc/sys, /sys, /proc/sysrq-trigger,
67# /proc/latency_stats, /proc/acpi, /proc/timer_stats, /proc/fs and /proc/irq
68# will be made read-only to all processes of the unit. Usually, tunable
69# kernel variables should only be written at boot-time, with the sysctl.d(5)
70# mechanism. Almost no services need to write to these at runtime; it is hence
71# recommended to turn this on for most services.
72##safer##ProtectKernelTunables=true
73
74# The Linux Control Groups (cgroups(7)) hierarchies accessible through
75# /sys/fs/cgroup will be made read-only to all processes of the unit.
76# Except for container managers no services should require write access
77# to the control groups hierarchies; it is hence recommended to turn this
78# on for most services
79##safer##ProtectControlGroups=true
80
81# Any attempts to enable realtime scheduling in a process of the unit are
82# refused.
83##safer##RestrictRealtime=true
84
85# Takes away the ability to create or manage any kind of namespace
86##safer##RestrictNamespaces=true
87
88[Install]
89WantedBy=multi-user.target
diff --git a/slab_automove_extstore.c b/slab_automove_extstore.c
index d9b62b9..a3012d7 100644
--- a/slab_automove_extstore.c
+++ b/slab_automove_extstore.c
@@ -20,6 +20,7 @@ struct window_data {
20 uint64_t dirty;20 uint64_t dirty;
21 uint64_t evicted;21 uint64_t evicted;
22 unsigned int excess_free;22 unsigned int excess_free;
23 unsigned int relaxed;
23};24};
2425
25struct window_global {26struct window_global {
@@ -90,6 +91,7 @@ static void window_sum(struct window_data *wd, struct window_data *w,
90 w->dirty += d->dirty;91 w->dirty += d->dirty;
91 w->evicted += d->evicted;92 w->evicted += d->evicted;
92 w->excess_free += d->excess_free;93 w->excess_free += d->excess_free;
94 w->relaxed += d->relaxed;
93 }95 }
94}96}
9597
@@ -121,6 +123,15 @@ static void global_pool_check(slab_automove *a) {
121 }123 }
122}124}
123125
126/* A percentage of memory is configured to be held "free" as buffers for the
127 * external storage system.
128 * % of global memory is desired in the global page pool
129 * each slab class has a % of free chunks desired based on how much memory is
130 * currently in the class. This allows time for extstore to flush data when
131 * spikes or waves of set data arrive.
132 * The global page pool reserve acts as a secondary buffer for any slab class,
133 * which helps absorb shifts in which class is active.
134 */
124static void memcheck(slab_automove *a) {135static void memcheck(slab_automove *a) {
125 unsigned int total_pages = 0;136 unsigned int total_pages = 0;
126 if (current_time < a->last_memcheck_run + MEMCHECK_PERIOD)137 if (current_time < a->last_memcheck_run + MEMCHECK_PERIOD)
@@ -143,6 +154,11 @@ static void memcheck(slab_automove *a) {
143 a->free_mem[0] = total_pages * a->free_ratio;154 a->free_mem[0] = total_pages * a->free_ratio;
144}155}
145156
157static struct window_data *get_window_data(slab_automove *a, int class) {
158 int w_offset = class * a->window_size;
159 return &a->window_data[w_offset + (a->window_cur % a->window_size)];
160}
161
146void slab_automove_extstore_run(void *arg, int *src, int *dst) {162void slab_automove_extstore_run(void *arg, int *src, int *dst) {
147 slab_automove *a = (slab_automove *)arg;163 slab_automove *a = (slab_automove *)arg;
148 int n;164 int n;
@@ -170,15 +186,16 @@ void slab_automove_extstore_run(void *arg, int *src, int *dst) {
170 for (n = POWER_SMALLEST; n < MAX_NUMBER_OF_SLAB_CLASSES; n++) {186 for (n = POWER_SMALLEST; n < MAX_NUMBER_OF_SLAB_CLASSES; n++) {
171 bool small_slab = a->sam_before[n].chunk_size < a->item_size187 bool small_slab = a->sam_before[n].chunk_size < a->item_size
172 ? true : false;188 ? true : false;
173 int w_offset = n * a->window_size;189 bool free_enough = false;
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);
175 // summarize the window-up-to-now.191 // summarize the window-up-to-now.
176 memset(&w_sum, 0, sizeof(struct window_data));192 memset(&w_sum, 0, sizeof(struct window_data));
193 int w_offset = n * a->window_size;
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);
178 memset(wd, 0, sizeof(struct window_data));195 memset(wd, 0, sizeof(struct window_data));
179196
180 // if page delta, or evicted delta, mark window dirty197 // if page delta, oom, or evicted delta, mark window dirty
181 // (or outofmemory)198 // classes marked dirty cannot donate memory back to global pool.
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 ||
183 a->iam_after[n].outofmemory - a->iam_before[n].outofmemory > 0) {200 a->iam_after[n].outofmemory - a->iam_before[n].outofmemory > 0) {
184 wd->evicted = 1;201 wd->evicted = 1;
@@ -188,7 +205,14 @@ void slab_automove_extstore_run(void *arg, int *src, int *dst) {
188 wd->dirty = 1;205 wd->dirty = 1;
189 }206 }
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.
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
209 // page of memory, or the crawler is freeing memory.
210 if (a->sam_after[n].free_chunks > a->free_mem[n]) {
211 free_enough = true;
212 }
213 // double the free requirements means we may have memory we can
214 // reclaim to global, if it stays this way for the whole window.
215 if (a->sam_after[n].free_chunks > (a->free_mem[n] * 2) && a->free_mem[n] > 0) {
192 wd->excess_free = 1;216 wd->excess_free = 1;
193 }217 }
194218
@@ -198,7 +222,9 @@ void slab_automove_extstore_run(void *arg, int *src, int *dst) {
198 // grab age as average of window total222 // grab age as average of window total
199 uint64_t age = w_sum.age / a->window_size;223 uint64_t age = w_sum.age / a->window_size;
200224
201 // if > N free chunks and not dirty, make decision.225 // if > N free chunks and not dirty, reclaim memory
226 // small slab classes aren't age balanced and rely more on global
227 // pool. reclaim them more aggressively.
202 if (a->sam_after[n].free_chunks > a->sam_after[n].chunks_per_page * MIN_PAGES_FOR_RECLAIM228 if (a->sam_after[n].free_chunks > a->sam_after[n].chunks_per_page * MIN_PAGES_FOR_RECLAIM
203 && w_sum.dirty == 0) {229 && w_sum.dirty == 0) {
204 if (small_slab) {230 if (small_slab) {
@@ -214,19 +240,22 @@ void slab_automove_extstore_run(void *arg, int *src, int *dst) {
214 }240 }
215 }241 }
216242
217 // if oldest and have enough pages, is oldest243 if (!small_slab) {
218 if (!small_slab244 // if oldest and have enough pages, is oldest
219 && age > oldest_age245 if (age > oldest_age
220 && a->sam_after[n].total_pages > MIN_PAGES_FOR_SOURCE) {246 && a->sam_after[n].total_pages > MIN_PAGES_FOR_SOURCE) {
221 oldest = n;247 oldest = n;
222 oldest_age = age;248 oldest_age = age;
223 }249 }
224250
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.
226 if (!small_slab && age < youngest_age && a->sam_after[n].total_pages != 0252 // (if it was relaxed recently, and is currently "free enough")
227 && w_sum.excess_free < a->window_size) {253 if (age < youngest_age && a->sam_after[n].total_pages != 0
228 youngest = n;254 && w_sum.excess_free < a->window_size
229 youngest_age = age;255 && !(w_sum.relaxed && free_enough)) {
256 youngest = n;
257 youngest_age = age;
258 }
230 }259 }
231 }260 }
232261
@@ -239,28 +268,29 @@ void slab_automove_extstore_run(void *arg, int *src, int *dst) {
239 return;268 return;
240269
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) {
242 /**src = 0;271 if (a->sam_after[youngest].free_chunks <= a->free_mem[youngest]) {
243 *dst = youngest;*/272 *src = 0;
244 /* TODO: No current way to directly assign page from 0 to elsewhere.273 *dst = youngest;
245 * Do a hack by setting the youngest's free mem limiter to274 }
246 * zero and re-running memcheck in the next second.275 struct window_data *wd = get_window_data(a, youngest);
247 * If set rates are very high and the pool is too low, this can bottom276 // "relaxing" here and below allows us to skip classes which will
248 * out...277 // never grow or are growing slowly, more quickly finding other
249 */278 // classes which violate the age ratio.
250 // schedule a memcheck run for "soon" to keep the limit zeroed out279 wd->relaxed = 1;
251 // while the pool stays too high. This will also allow multiple
252 // classes to zero out over time.
253 a->last_memcheck_run = current_time - (MEMCHECK_PERIOD - 2);
254 a->settings->ext_free_memchunks[youngest] = 0;
255 } else if (!too_free && wg_sum.pool_low && oldest != -1) {280 } else if (!too_free && wg_sum.pool_low && oldest != -1) {
256 *src = oldest;281 *src = oldest;
257 *dst = 0;282 *dst = 0;
258 } else if (!too_free && youngest != -1 && oldest != -1 && youngest != oldest) {283 } else if (!too_free && youngest != -1 && oldest != -1 && youngest != oldest) {
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.
260 if (a->sam_after[youngest].free_chunks <= a->free_mem[youngest]285 if (youngest_age < ((double)oldest_age * a->max_age_ratio)) {
261 && youngest_age < ((double)oldest_age * a->max_age_ratio)) {286 struct window_data *wd = get_window_data(a, youngest);
262 *src = oldest;287 wd->relaxed = 1;
263 *dst = youngest;288 // only actually assign more memory if it's absorbed what it has
289 if (a->sam_after[youngest].free_chunks <= a->free_mem[youngest]) {
290 *src = 0;
291 *dst = youngest;
292
293 }
264 }294 }
265 }295 }
266 return;296 return;
diff --git a/slabs.c b/slabs.c
index cedb1e8..200d575 100644
--- a/slabs.c
+++ b/slabs.c
@@ -678,7 +678,7 @@ static int slab_rebalance_start(void) {
678678
679 pthread_mutex_lock(&slabs_lock);679 pthread_mutex_lock(&slabs_lock);
680680
681 if (slab_rebal.s_clsid < POWER_SMALLEST ||681 if (slab_rebal.s_clsid < SLAB_GLOBAL_PAGE_POOL ||
682 slab_rebal.s_clsid > power_largest ||682 slab_rebal.s_clsid > power_largest ||
683 slab_rebal.d_clsid < SLAB_GLOBAL_PAGE_POOL ||683 slab_rebal.d_clsid < SLAB_GLOBAL_PAGE_POOL ||
684 slab_rebal.d_clsid > power_largest ||684 slab_rebal.d_clsid > power_largest ||
@@ -707,8 +707,11 @@ static int slab_rebalance_start(void) {
707 (s_cls->size * s_cls->perslab);707 (s_cls->size * s_cls->perslab);
708 slab_rebal.slab_pos = slab_rebal.slab_start;708 slab_rebal.slab_pos = slab_rebal.slab_start;
709 slab_rebal.done = 0;709 slab_rebal.done = 0;
710 // Don't need to do chunk move work if page is in global pool.
711 if (slab_rebal.s_clsid == SLAB_GLOBAL_PAGE_POOL) {
712 slab_rebal.done = 1;
713 }
710714
711 /* Also tells do_item_get to search for items in this slab */
712 slab_rebalance_signal = 2;715 slab_rebalance_signal = 2;
713716
714 if (settings.verbose > 1) {717 if (settings.verbose > 1) {
@@ -862,7 +865,9 @@ static int slab_rebalance_move(void) {
862 // Only safe to hold slabs lock because refcount865 // Only safe to hold slabs lock because refcount
863 // can't drop to 0 until we release item lock.866 // can't drop to 0 until we release item lock.
864 STORAGE_delete(storage, it);867 STORAGE_delete(storage, it);
868 pthread_mutex_unlock(&slabs_lock);
865 do_item_unlink(it, hv);869 do_item_unlink(it, hv);
870 pthread_mutex_lock(&slabs_lock);
866 }871 }
867 status = MOVE_BUSY;872 status = MOVE_BUSY;
868 } else {873 } else {
@@ -1187,7 +1192,7 @@ static enum reassign_result_type do_slabs_reassign(int src, int dst) {
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 */
1188 }1193 }
11891194
1190 if (src < POWER_SMALLEST || src > power_largest ||1195 if (src < SLAB_GLOBAL_PAGE_POOL || src > power_largest ||
1191 dst < SLAB_GLOBAL_PAGE_POOL || dst > power_largest)1196 dst < SLAB_GLOBAL_PAGE_POOL || dst > power_largest)
1192 return REASSIGN_BADCLASS;1197 return REASSIGN_BADCLASS;
11931198
diff --git a/t/issue_67.t b/t/issue_67.t
index 69c869f..b2d374f 100644
--- a/t/issue_67.t
+++ b/t/issue_67.t
@@ -77,11 +77,11 @@ sub when {
7777
78# Disabling the defaults since it conflicts with a running instance.78# Disabling the defaults since it conflicts with a running instance.
79# when('no arguments', '', 11211, 11211);79# when('no arguments', '', 11211, 11211);
80when('specifying tcp port', '-p 11212', 11212, 11212);80when('specifying tcp port', '-p 11212', 11212, -1);
81when('specifying udp port', '-U 11222', 11222, 11222);81when('specifying udp port', '-U 11222', 11222, 11222);
82when('specifying tcp ephemeral port', '-p -1', 0, 0);82when('specifying tcp ephemeral port', '-p -1', 0, 0);
83when('specifying udp ephemeral port', '-U -1', 0, 0);83when('specifying udp ephemeral port', '-U -1', 0, 0);
84when('tcp port disabled', '-p 0', -1, 11211);84when('tcp port disabled', '-p 0', -1, -1);
85when('udp port disabled', '-U 0', 11211, -1);85when('udp port disabled', '-U 0', 11211, -1);
86when('specifying tcp and udp ports', '-p 11232 -U 11233', 11232, 11233);86when('specifying tcp and udp ports', '-p 11232 -U 11233', 11232, 11233);
87when('specifying tcp and disabling udp', '-p 11242 -U 0', 11242, -1);87when('specifying tcp and disabling udp', '-p 11242 -U 0', 11242, -1);
diff --git a/thread.c b/thread.c
index df05d5f..d17a387 100644
--- a/thread.c
+++ b/thread.c
@@ -309,7 +309,16 @@ void accept_new_conns(const bool do_accept) {
309 * Set up a thread's information.309 * Set up a thread's information.
310 */310 */
311static void setup_thread(LIBEVENT_THREAD *me) {311static void setup_thread(LIBEVENT_THREAD *me) {
312#if defined(LIBEVENT_VERSION_NUMBER) && LIBEVENT_VERSION_NUMBER >= 0x02000101
313 struct event_config *ev_config;
314 ev_config = event_config_new();
315 event_config_set_flag(ev_config, EVENT_BASE_FLAG_NOLOCK);
316 me->base = event_base_new_with_config(ev_config);
317 event_config_free(ev_config);
318#else
312 me->base = event_init();319 me->base = event_init();
320#endif
321
313 if (! me->base) {322 if (! me->base) {
314 fprintf(stderr, "Can't allocate event base\n");323 fprintf(stderr, "Can't allocate event base\n");
315 exit(1);324 exit(1);
@@ -374,6 +383,8 @@ static void *worker_libevent(void *arg) {
374 register_thread_initialized();383 register_thread_initialized();
375384
376 event_base_loop(me->base, 0);385 event_base_loop(me->base, 0);
386
387 event_base_free(me->base);
377 return NULL;388 return NULL;
378}389}
379390
diff --git a/timedrun.c b/timedrun.c
index 6d7afb3..6888453 100644
--- a/timedrun.c
+++ b/timedrun.c
@@ -17,7 +17,7 @@ static void caught_signal(int which)
17static int wait_for_process(pid_t pid)17static int wait_for_process(pid_t pid)
18{18{
19 int rv = EX_SOFTWARE;19 int rv = EX_SOFTWARE;
20 int stats = 0;20 int status = 0;
21 int i = 0;21 int i = 0;
22 struct sigaction sig_handler;22 struct sigaction sig_handler;
2323
@@ -32,12 +32,12 @@ static int wait_for_process(pid_t pid)
3232
33 /* Loop forever waiting for the process to quit */33 /* Loop forever waiting for the process to quit */
34 for (i = 0; ;i++) {34 for (i = 0; ;i++) {
35 pid_t p = waitpid(pid, &stats, 0);35 pid_t p = waitpid(pid, &status, 0);
36 if (p == pid) {36 if (p == pid) {
37 /* child exited. Let's get out of here */37 /* child exited. Let's get out of here */
38 rv = WIFEXITED(stats) ?38 rv = WIFEXITED(status) ?
39 WEXITSTATUS(stats) :39 WEXITSTATUS(status) :
40 (0x80 | WTERMSIG(stats));40 (0x80 | WTERMSIG(status));
41 break;41 break;
42 } else {42 } else {
43 int sig = 0;43 int sig = 0;
diff --git a/trace.h b/trace.h
index dc792a0..94e585d 100644
--- a/trace.h
+++ b/trace.h
@@ -4,11 +4,11 @@
4#ifdef ENABLE_DTRACE4#ifdef ENABLE_DTRACE
5#include "memcached_dtrace.h"5#include "memcached_dtrace.h"
6#else6#else
7#define MEMCACHED_ASSOC_DELETE(arg0, arg1, arg2)7#define MEMCACHED_ASSOC_DELETE(arg0, arg1)
8#define MEMCACHED_ASSOC_DELETE_ENABLED() (0)8#define MEMCACHED_ASSOC_DELETE_ENABLED() (0)
9#define MEMCACHED_ASSOC_FIND(arg0, arg1, arg2)9#define MEMCACHED_ASSOC_FIND(arg0, arg1, arg2)
10#define MEMCACHED_ASSOC_FIND_ENABLED() (0)10#define MEMCACHED_ASSOC_FIND_ENABLED() (0)
11#define MEMCACHED_ASSOC_INSERT(arg0, arg1, arg2)11#define MEMCACHED_ASSOC_INSERT(arg0, arg1)
12#define MEMCACHED_ASSOC_INSERT_ENABLED() (0)12#define MEMCACHED_ASSOC_INSERT_ENABLED() (0)
13#define MEMCACHED_COMMAND_ADD(arg0, arg1, arg2, arg3, arg4)13#define MEMCACHED_COMMAND_ADD(arg0, arg1, arg2, arg3, arg4)
14#define MEMCACHED_COMMAND_ADD_ENABLED() (0)14#define MEMCACHED_COMMAND_ADD_ENABLED() (0)
diff --git a/version.m4 b/version.m4
index d763a82..4a02156 100644
--- a/version.m4
+++ b/version.m4
@@ -1 +1 @@
1m4_define([VERSION_NUMBER], [1.5.4])1m4_define([VERSION_NUMBER], [1.5.6])

Subscribers

People subscribed via source and target branches