Support configurable file backed scratch

This commit is contained in:
John Sully 2019-02-01 13:54:59 -05:00
parent 5e6b9b9c54
commit a476fdfd8c
9 changed files with 107 additions and 34 deletions

View File

@ -166,9 +166,9 @@ REDIS_SERVER_NAME=redis-server
REDIS_SENTINEL_NAME=redis-sentinel
REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o acl.o storage.o
REDIS_CLI_NAME=redis-cli
REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o siphash.o crc16.o storage.o
REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o siphash.o crc16.o storage-lite.o
REDIS_BENCHMARK_NAME=redis-benchmark
REDIS_BENCHMARK_OBJ=ae.o anet.o redis-benchmark.o adlist.o zmalloc.o redis-benchmark.o storage.o
REDIS_BENCHMARK_OBJ=ae.o anet.o redis-benchmark.o adlist.o zmalloc.o redis-benchmark.o storage-lite.o
REDIS_CHECK_RDB_NAME=redis-check-rdb
REDIS_CHECK_AOF_NAME=redis-check-aof

View File

@ -804,6 +804,8 @@ void loadServerConfigFromString(char *config) {
err = sentinelHandleConfiguration(argv+1,argc-1);
if (err) goto loaderr;
}
} else if (!strcasecmp(argv[0],"scratch-file-path")) {
storage_init(argv[1]);
} else {
err = "Bad directive or wrong number of arguments"; goto loaderr;
}

View File

@ -39,7 +39,7 @@
/* ===================== Creation and parsing of objects ==================== */
robj *createObject(int type, void *ptr) {
robj *o = salloc_obj(); //zmalloc(sizeof(*o), MALLOC_SHARED);
robj *o = zmalloc(sizeof(*o), MALLOC_SHARED);
o->type = type;
o->encoding = OBJ_ENCODING_RAW;
o->ptr = ptr;
@ -362,10 +362,7 @@ void decrRefCount(robj *o) {
case OBJ_STREAM: freeStreamObject(o); break;
default: serverPanic("Unknown object type"); break;
}
if (o->type == OBJ_STRING && o->encoding == OBJ_ENCODING_EMBSTR)
zfree(o);
else
sfree_obj(o);
zfree(o);
} else {
if (o->refcount <= 0) serverPanic("decrRefCount against refcount <= 0");
if (o->refcount != OBJ_SHARED_REFCOUNT) o->refcount--;

View File

@ -653,7 +653,7 @@ int main(int argc, const char **argv) {
client c;
storage_init();
storage_init(NULL);
srandom(time(NULL));
signal(SIGHUP, SIG_IGN);

View File

@ -7176,7 +7176,7 @@ static void intrinsicLatencyMode(void) {
int main(int argc, char **argv) {
int firstarg;
storage_init();
storage_init(NULL);
config.hostip = sdsnew("127.0.0.1");
config.hostport = 6379;
config.hostsocket = NULL;

View File

@ -4740,7 +4740,7 @@ int main(int argc, char **argv) {
struct timeval tv;
int j;
storage_init();
storage_init(NULL);
#ifdef REDIS_TEST
if (argc == 3 && !strcasecmp(argv[1], "test")) {

41
src/storage-lite.c Normal file
View File

@ -0,0 +1,41 @@
#include <stdlib.h>
#include <stdio.h>
#include <memkind.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <unistd.h>
#include <inttypes.h>
#include "storage.h"
#include <assert.h>
// initialize the memory subsystem.
// NOTE: This may be called twice, first with NULL specifying we should use ram
// later, after the configuration file is loaded with a path to where we should
// place our temporary file.
void storage_init(const char *tmpfilePath)
{
assert(tmpfilePath == NULL);
(void)tmpfilePath;
}
void *salloc(size_t cb, enum MALLOC_CLASS class)
{
(void)class;
return malloc(cb);
}
void *scalloc(size_t cb, size_t c, enum MALLOC_CLASS class)
{
(void)class;
return calloc(cb, c);
}
void sfree(void *pv)
{
free(pv);
}
void *srealloc(void *pv, size_t cb)
{
return realloc(pv, cb);
}

View File

@ -10,7 +10,7 @@
#include "storage.h"
struct memkind *mkdisk = NULL;
static char *PMEM_DIR = "/mnt/btrfs_scratch/";
static const char *PMEM_DIR = NULL;
void handle_prefork();
void handle_postfork_parent();
@ -85,9 +85,6 @@ void *pool_alloc(struct alloc_pool *ppool)
}
}
#pragma weak serverLog
void serverLog(int level, const char*fmt, ...){}
void pool_free(struct alloc_pool *ppool, void *pv)
{
struct object_page *cur = ppool->pobjpageHead;
@ -113,18 +110,62 @@ void pool_free(struct alloc_pool *ppool, void *pv)
struct alloc_pool poolobj;
struct alloc_pool poolembstrobj;
void storage_init()
int forkFile()
{
int errv = memkind_create_pmem(PMEM_DIR, 0, &mkdisk);
if (errv)
int fdT;
memkind_tmpfile(PMEM_DIR, &fdT);
if (ioctl(fdT, FICLONE, memkind_fd(mkdisk)) == -1)
{
fprintf(stderr, "Memory pool creation failed: %d\n", errv);
exit(EXIT_FAILURE);
return -1;
}
pool_initialize(&poolobj, sizeof(robj));
pool_initialize(&poolembstrobj, EMBSTR_ROBJ_SIZE);
return fdT;
}
pthread_atfork(handle_prefork, handle_postfork_parent, handle_postfork_child);
// initialize the memory subsystem.
// NOTE: This may be called twice, first with NULL specifying we should use ram
// later, after the configuration file is loaded with a path to where we should
// place our temporary file.
void storage_init(const char *tmpfilePath)
{
if (tmpfilePath == NULL)
{
serverAssert(mkdisk == NULL);
mkdisk = MEMKIND_DEFAULT;
}
else
{
// First create the file
serverAssert(mkdisk == MEMKIND_DEFAULT);
PMEM_DIR = memkind_malloc(MEMKIND_DEFAULT, strlen(tmpfilePath));
strcpy((char*)PMEM_DIR, tmpfilePath);
int errv = memkind_create_pmem(PMEM_DIR, 0, &mkdisk);
if (errv == MEMKIND_ERROR_INVALID)
{
serverLog(LOG_CRIT, "Memory pool creation failed: %s", strerror(errno));
exit(EXIT_FAILURE);
}
else if (errv)
{
char msgbuf[1024];
memkind_error_message(errv, msgbuf, 1024);
serverLog(LOG_CRIT, "Memory pool creation failed: %s", msgbuf);
exit(EXIT_FAILURE);
}
// Next test if COW is working
int fdTest = forkFile();
if (fdTest < 0)
{
serverLog(LOG_ERR, "Scratch file system does not support Copy on Write. To fix this scratch-file-path must point to a path on a filesystem which supports copy on write, such as btrfs.");
exit(EXIT_FAILURE);
}
close(fdTest);
pool_initialize(&poolobj, sizeof(robj));
pool_initialize(&poolembstrobj, EMBSTR_ROBJ_SIZE);
pthread_atfork(handle_prefork, handle_postfork_parent, handle_postfork_child);
}
}
@ -184,12 +225,9 @@ void *srealloc(void *pv, size_t cb)
int fdNew = -1;
void handle_prefork()
{
memkind_tmpfile(PMEM_DIR, &fdNew);
if (ioctl(fdNew, FICLONE, memkind_fd(mkdisk)) == -1)
{
perror("failed to fork file");
exit(EXIT_FAILURE);
}
fdNew = forkFile();
if (fdNew < 0)
serverLog(LOG_ERR, "Failed to clone scratch file");
}
void handle_postfork_parent()

View File

@ -9,12 +9,7 @@ enum MALLOC_CLASS
MALLOC_SHARED,
};
void storage_init(void);
struct redisObject *salloc_obj();
void sfree_obj(struct redisObject *obj);
struct redisObject *salloc_objembstr();
void sfree_objembstr(struct redisObject *obj);
void storage_init(const char *tmpfilePath);
void *salloc(size_t cb, enum MALLOC_CLASS class);
void *scalloc(size_t cb, size_t c, enum MALLOC_CLASS class);