fellow_log: Prevent starting with too little memory

Part of the solution to #54
parent 286e6a9b
...@@ -295,7 +295,9 @@ fellow_log_dbg_SOURCES = fellow_log_dbg.c \ ...@@ -295,7 +295,9 @@ fellow_log_dbg_SOURCES = fellow_log_dbg.c \
fellow_task.h \ fellow_task.h \
fellow_testenv.h \ fellow_testenv.h \
fellow_testenv.c \ fellow_testenv.c \
foreign/vend.h foreign/vend.h \
pow2_units.h \
pow2_units.c
fellow_log_dbg_SOURCES += $(io_ioctl_sources) fellow_log_dbg_SOURCES += $(io_ioctl_sources)
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#include "foreign/qdef.h" #include "foreign/qdef.h"
#include "vqueue.h" #include "vqueue.h"
#include "bitf_segmentation.h" #include "bitf_segmentation.h"
#include "pow2_units.h"
#include "foreign/vend.h" #include "foreign/vend.h"
...@@ -550,8 +551,9 @@ struct fellow_disk_data_hdr { ...@@ -550,8 +551,9 @@ struct fellow_disk_data_hdr {
#define FELLOW_DISK_DATA_HDR_CHK_LEN \ #define FELLOW_DISK_DATA_HDR_CHK_LEN \
(sizeof(struct fellow_disk_data_hdr) - FELLOW_DISK_DATA_HDR_CHK_START) (sizeof(struct fellow_disk_data_hdr) - FELLOW_DISK_DATA_HDR_CHK_START)
struct fellow_disk_log_info log_info; struct fellow_disk_log_info log_info;
uint64_t objsize;
uint8_t _pad[3959]; uint8_t _pad[3951];
uint8_t fht; uint8_t fht;
}; };
...@@ -1931,12 +1933,67 @@ fellow_io_log_submit(const struct fellow_fd *ffd, void *ioctx, ...@@ -1931,12 +1933,67 @@ fellow_io_log_submit(const struct fellow_fd *ffd, void *ioctx,
return (1); return (1);
} }
/*
* this is approximate, because we account overhead towards
* objects, also used space does not exactly match the numbers
* from the log buffer
*/
static uint64_t
fellow_objsize(struct fellow_fd *ffd)
{
const struct dle_stats *s;
size_t obj, del, spc, sz;
unsigned u;
if (ffd->rewriting)
return (0);
spc = buddy_space(ffd->dskbuddy, 1);
sz = buddy_size(ffd->dskbuddy);
AN(sz);
assert(sz >= spc);
sz -= spc;
if (pthread_mutex_trylock(&ffd->logmtx))
return (0);
for (u = 0; u < LOGREGIONS; u++) {
spc = ffd->log_info.log_region[u].size;
if (sz >= spc)
sz -= spc;
else
sz = 0;
}
s = &ffd->logbuf->dle_stats;
obj = s->obj_add;
del = s->obj_del_free;
if (ffd->rewriting)
sz = 0;
AZ(pthread_mutex_unlock(&ffd->logmtx)); //lint !e455
spc = N_HDR * MIN_FELLOW_BLOCK;
if (sz >= spc)
sz -= spc;
if (obj > del)
obj -= del;
if (obj == 0)
return (0);
return (sz / obj);
}
static int static int
fellow_io_write_hdr(struct fellow_fd *ffd) fellow_io_write_hdr(struct fellow_fd *ffd)
{ {
struct fellow_disk_data_hdr hdr struct fellow_disk_data_hdr hdr
__attribute__((aligned(MIN_FELLOW_BLOCK))); __attribute__((aligned(MIN_FELLOW_BLOCK)));
int32_t ssz; int32_t ssz;
size_t objsz;
CHECK_OBJ_NOTNULL(ffd, FELLOW_FD_MAGIC); CHECK_OBJ_NOTNULL(ffd, FELLOW_FD_MAGIC);
...@@ -1953,11 +2010,14 @@ fellow_io_write_hdr(struct fellow_fd *ffd) ...@@ -1953,11 +2010,14 @@ fellow_io_write_hdr(struct fellow_fd *ffd)
ffd->log_info.off.logblk, ffd->log_info.off.logblk,
ffd->log_info.off.pendblk); ffd->log_info.off.pendblk);
objsz = fellow_objsize(ffd);
INIT_OBJ(&hdr, FELLOW_DISK_DATA_HDR_MAGIC); INIT_OBJ(&hdr, FELLOW_DISK_DATA_HDR_MAGIC);
hdr.version = 1; hdr.version = 1;
hdr.fht = FH_SHA256; hdr.fht = FH_SHA256;
memcpy(&ffd->last_log_info, &ffd->log_info, sizeof hdr.log_info); memcpy(&ffd->last_log_info, &ffd->log_info, sizeof hdr.log_info);
memcpy(&hdr.log_info, &ffd->log_info, sizeof hdr.log_info); memcpy(&hdr.log_info, &ffd->log_info, sizeof hdr.log_info);
hdr.objsize = objsz;
fh(hdr.fht, hdr.fh, fh(hdr.fht, hdr.fh,
(char *)&hdr + FELLOW_DISK_DATA_HDR_CHK_START, (char *)&hdr + FELLOW_DISK_DATA_HDR_CHK_START,
FELLOW_DISK_DATA_HDR_CHK_LEN); FELLOW_DISK_DATA_HDR_CHK_LEN);
...@@ -6299,7 +6359,8 @@ fellow_log_init(const char *path, size_t wantsize, size_t objsz_hint, ...@@ -6299,7 +6359,8 @@ fellow_log_init(const char *path, size_t wantsize, size_t objsz_hint,
unsigned i; unsigned i;
unsigned entries; unsigned entries;
size_t sz; size_t sz;
int32_t ssz; int32_t ssz;
uint64_t objsize = 0;
char last_err[256] = ""; char last_err[256] = "";
const int *fl, tryflags[] = { const int *fl, tryflags[] = {
#ifdef O_DIRECT #ifdef O_DIRECT
...@@ -6437,6 +6498,8 @@ fellow_log_init(const char *path, size_t wantsize, size_t objsz_hint, ...@@ -6437,6 +6498,8 @@ fellow_log_init(const char *path, size_t wantsize, size_t objsz_hint,
ffd->active_hdr = i; ffd->active_hdr = i;
memcpy(&ffd->log_info, &hdr[i].log_info, sizeof ffd->log_info); memcpy(&ffd->log_info, &hdr[i].log_info, sizeof ffd->log_info);
if (hdr[i].objsize > 0)
objsize = hdr[i].objsize;
} }
if (*last_err != '\0') if (*last_err != '\0')
...@@ -6456,6 +6519,22 @@ fellow_log_init(const char *path, size_t wantsize, size_t objsz_hint, ...@@ -6456,6 +6519,22 @@ fellow_log_init(const char *path, size_t wantsize, size_t objsz_hint,
path, ffd->active_hdr, ffd->log_info.generation); path, ffd->active_hdr, ffd->log_info.generation);
} }
if (objsize > MIN_FELLOW_BLOCK)
sz = MEMBUDDY_MINSIZE(wantsize, objsize);
else
sz = 0;
if (buddy_size(membuddy) < sz) {
ffd->diag("\nfellow:\tFATAL: memsz too small for "
"actual objsize %zu < objsize_hint %zu!\n"
"fellow:\tlower objsize_hint to %s or "
"increase memsz to %s and restart.\n",
(size_t)objsize, objsz_hint,
pow2_unit(log2down(objsize)),
pow2_unit(log2up(sz)));
goto err_close;
}
if (fstat(ffd->fd, &st)) { if (fstat(ffd->fd, &st)) {
ffd->diag("fellow: fstat(%s) failed: %s (%d)\n", ffd->diag("fellow: fstat(%s) failed: %s (%d)\n",
path, strerror(errno), errno); path, strerror(errno), errno);
...@@ -6561,6 +6640,7 @@ fellow_log_init(const char *path, size_t wantsize, size_t objsz_hint, ...@@ -6561,6 +6640,7 @@ fellow_log_init(const char *path, size_t wantsize, size_t objsz_hint,
return (ffd); return (ffd);
err_close: err_close:
DBG("ERROR close %p", ffd);
close(ffd->fd); close(ffd->fd);
err_free: err_free:
FREE_OBJ(ffd); FREE_OBJ(ffd);
......
...@@ -20,7 +20,11 @@ ...@@ -20,7 +20,11 @@
* electronic and paper mail. * electronic and paper mail.
*/ */
const char * const pow2_units[] = { #include "config.h"
#include <assert.h>
#include "pow2_units.h"
const char * const pow2_units[POW2_MAX + 1] = {
[0] = "1B", [0] = "1B",
[1] = "2B", [1] = "2B",
[2] = "4B", [2] = "4B",
......
...@@ -20,4 +20,13 @@ ...@@ -20,4 +20,13 @@
* electronic and paper mail. * electronic and paper mail.
*/ */
extern const char * const pow2_units[]; #define POW2_MAX 80
extern const char * const pow2_units[POW2_MAX + 1];
static inline const char *
pow2_unit(unsigned u)
{
assert(u <= POW2_MAX);
return (pow2_units[u]);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment