fellow_cache: embed fdo in fco allocation if possible

Conflicts:
	src/fellow_cache.c
parent 4ed6c485
...@@ -323,7 +323,7 @@ struct fellow_disk_seglist { ...@@ -323,7 +323,7 @@ struct fellow_disk_seglist {
*/ */
#define FELLOW_DISK_SEGLIST_MAX_SEGS /* 65534 */ \ #define FELLOW_DISK_SEGLIST_MAX_SEGS /* 65534 */ \
(((((sizeof(struct fellow_disk_seg) << 16) + \ (unsigned)(((((sizeof(struct fellow_disk_seg) << 16) + \
sizeof(struct fellow_disk_seglist)) & ~FELLOW_BLOCK_ALIGN) - \ sizeof(struct fellow_disk_seglist)) & ~FELLOW_BLOCK_ALIGN) - \
sizeof(struct fellow_disk_seglist)) / \ sizeof(struct fellow_disk_seglist)) / \
sizeof(struct fellow_disk_seg)) sizeof(struct fellow_disk_seg))
...@@ -704,7 +704,7 @@ struct fellow_cache_obj { ...@@ -704,7 +704,7 @@ struct fellow_cache_obj {
*/ */
#define FDO_MAX_EMBED_SEGS \ #define FDO_MAX_EMBED_SEGS \
((MIN_FELLOW_BLOCK - sizeof(struct fellow_cache_obj)) \ (unsigned)((MIN_FELLOW_BLOCK - sizeof(struct fellow_cache_obj)) \
/ sizeof(struct fellow_cache_seg)) / sizeof(struct fellow_cache_seg))
#define fellow_cache_obj_size(fco) \ #define fellow_cache_obj_size(fco) \
...@@ -1158,6 +1158,9 @@ fellow_disk_obj_trim(const struct fellow_cache *fc, ...@@ -1158,6 +1158,9 @@ fellow_disk_obj_trim(const struct fellow_cache *fc,
fdo = fellow_disk_obj(fcs); fdo = fellow_disk_obj(fcs);
CHECK_OBJ_NOTNULL(fdo, FELLOW_DISK_OBJ_MAGIC); CHECK_OBJ_NOTNULL(fdo, FELLOW_DISK_OBJ_MAGIC);
// not if already relocated
assert(fdo == fcs->alloc.ptr);
fdsl = fellow_disk_obj_fdsl(fdo); fdsl = fellow_disk_obj_fdsl(fdo);
CHECK_OBJ(fdsl, FELLOW_DISK_SEGLIST_MAGIC); CHECK_OBJ(fdsl, FELLOW_DISK_SEGLIST_MAGIC);
...@@ -2085,16 +2088,16 @@ fellow_cache_obj_new( ...@@ -2085,16 +2088,16 @@ fellow_cache_obj_new(
struct buddy_reqs *reqs; struct buddy_reqs *reqs;
struct buddy_ptr_extent fco_mem = buddy_ptr_extent_nil; struct buddy_ptr_extent fco_mem = buddy_ptr_extent_nil;
struct buddy_ptr_extent fdo_mem = buddy_ptr_extent_nil; struct buddy_ptr_extent fdo_mem = buddy_ptr_extent_nil;
size_t asz, mem_sz, ssz; size_t mem_sz, ssz;
unsigned u; unsigned u;
DBG("arg dsk_sz %zu nseg_guess %u", dsk_sz, nseg_guess); DBG("arg dsk_sz %zu nseg_guess %u", dsk_sz, nseg_guess);
if (nseg_guess == 0) AN(nseg_guess);
nseg_guess = 1;
// for busy objects, mem_sz may be less than MIN_FELLOW_BLOCK
mem_sz = (size_t)1 << log2up(sizeof *fco + nseg_guess * sizeof *fcs); mem_sz = (size_t)1 << log2up(sizeof *fco + nseg_guess * sizeof *fcs);
asz = (size_t)1 << log2up(dsk_sz); assert(mem_sz <= MIN_FELLOW_BLOCK);
// dowry is largest, so we allocate it first // dowry is largest, so we allocate it first
reqs = BUDDY_REQS_STK(fc->membuddy, 4); reqs = BUDDY_REQS_STK(fc->membuddy, 4);
...@@ -2103,14 +2106,12 @@ fellow_cache_obj_new( ...@@ -2103,14 +2106,12 @@ fellow_cache_obj_new(
AN(buddy_req_page(reqs, fc->tune->chunk_exponent, 0)); AN(buddy_req_page(reqs, fc->tune->chunk_exponent, 0));
if (fbo_mem != NULL) if (fbo_mem != NULL)
AN(buddy_req_extent(reqs, sizeof(struct fellow_busy), 0)); AN(buddy_req_extent(reqs, sizeof(struct fellow_busy), 0));
if (mem_sz > asz) {
AN(buddy_req_extent(reqs, mem_sz, 0)); assert(dsk_sz == fellow_rndup(fc->ffd, dsk_sz));
AN(buddy_req_extent(reqs, asz, 0)); assert(dsk_sz >= mem_sz);
} AN(buddy_req_extent(reqs, dsk_sz, 0));
else { AN(buddy_req_extent(reqs, mem_sz, 0));
AN(buddy_req_extent(reqs, asz, 0));
AN(buddy_req_extent(reqs, mem_sz, 0));
}
u = buddy_alloc_wait(reqs); u = buddy_alloc_wait(reqs);
if (FC_INJ || u != 2 + (dowry ? 1 : 0) + (fbo_mem ? 1 : 0)) { if (FC_INJ || u != 2 + (dowry ? 1 : 0) + (fbo_mem ? 1 : 0)) {
buddy_alloc_wait_done(reqs); buddy_alloc_wait_done(reqs);
...@@ -2125,14 +2126,8 @@ fellow_cache_obj_new( ...@@ -2125,14 +2126,8 @@ fellow_cache_obj_new(
if (fbo_mem != NULL) if (fbo_mem != NULL)
*fbo_mem = buddy_get_next_ptr_extent(reqs); *fbo_mem = buddy_get_next_ptr_extent(reqs);
if (mem_sz > asz) { fdo_mem = buddy_get_next_ptr_extent(reqs);
fco_mem = buddy_get_next_ptr_extent(reqs); fco_mem = buddy_get_next_ptr_extent(reqs);
fdo_mem = buddy_get_next_ptr_extent(reqs);
}
else {
fdo_mem = buddy_get_next_ptr_extent(reqs);
fco_mem = buddy_get_next_ptr_extent(reqs);
}
buddy_alloc_wait_done(reqs); buddy_alloc_wait_done(reqs);
...@@ -2972,6 +2967,12 @@ fellow_cache_obj_trim(const struct fellow_cache *fc, ...@@ -2972,6 +2967,12 @@ fellow_cache_obj_trim(const struct fellow_cache *fc,
CHECK_OBJ_NOTNULL(fc, FELLOW_CACHE_MAGIC); CHECK_OBJ_NOTNULL(fc, FELLOW_CACHE_MAGIC);
CHECK_OBJ_NOTNULL(fco, FELLOW_CACHE_OBJ_MAGIC); CHECK_OBJ_NOTNULL(fco, FELLOW_CACHE_OBJ_MAGIC);
// no trim if fdo is embedded - XXX cleaner way?
if (FCO_FCS(fco)->alloc.ptr == NULL)
return;
assert(FCO_FDO(fco) == FCO_FCS(fco)->alloc.ptr);
fcsl = &fco->fcsl_embed; fcsl = &fco->fcsl_embed;
CHECK_OBJ(fcsl, FELLOW_CACHE_SEGLIST_MAGIC); CHECK_OBJ(fcsl, FELLOW_CACHE_SEGLIST_MAGIC);
fdsl = fcsl->fdsl; fdsl = fcsl->fdsl;
...@@ -5253,7 +5254,7 @@ fellow_cache_obj_prepread(struct fellow_cache *fc, fellow_disk_block fdba, ...@@ -5253,7 +5254,7 @@ fellow_cache_obj_prepread(struct fellow_cache *fc, fellow_disk_block fdba,
if (! PAOK(sz)) if (! PAOK(sz))
return (FCR_IOFAIL("bad size")); return (FCR_IOFAIL("bad size"));
fcr = fellow_cache_obj_new(fc, sz, 0, NULL, fcr = fellow_cache_obj_new(fc, sz, FDO_MAX_EMBED_SEGS, NULL,
crit ? NULL : &dowry, crit ? NULL : &dowry,
crit ? FEP_OHLCK : FEP_GET); crit ? FEP_OHLCK : FEP_GET);
if (fcr.status != fcr_ok) if (fcr.status != fcr_ok)
...@@ -5381,6 +5382,8 @@ struct objcore **ocp, uintptr_t priv2, unsigned crit) ...@@ -5381,6 +5382,8 @@ struct objcore **ocp, uintptr_t priv2, unsigned crit)
fellow_disk_block fdba; fellow_disk_block fdba;
unsigned oref = 0; unsigned oref = 0;
const char *err; const char *err;
char *ptr;
size_t spc, sz;
int r; int r;
CHECK_OBJ_NOTNULL(fc, FELLOW_CACHE_MAGIC); CHECK_OBJ_NOTNULL(fc, FELLOW_CACHE_MAGIC);
...@@ -5481,28 +5484,24 @@ struct objcore **ocp, uintptr_t priv2, unsigned crit) ...@@ -5481,28 +5484,24 @@ struct objcore **ocp, uintptr_t priv2, unsigned crit)
if (err != NULL) if (err != NULL)
goto err; goto err;
// or because oa_inlog_bit // |= is because of oa_inlog_bit
if (fco->oc) if (fco->oc)
fco->oc->oa_present |= fdoa2oa_present(fdo->fdoa_present); fco->oc->oa_present |= fdoa2oa_present(fdo->fdoa_present);
fdsl = fellow_disk_obj_fdsl(fdo);
/* the check of the fdo-embedded fdsl needs to happen before trim, /* the check of the fdo-embedded fdsl needs to happen before trim,
* because both trim and relocation change data after the used part of * because both trim and relocation change data after the used part of
* the fdsl * the fdsl
*/ */
fdsl = fellow_disk_obj_fdsl(fdo);
err = fellow_disk_seglist_check(fdsl); err = fellow_disk_seglist_check(fdsl);
if (err != NULL) if (err != NULL)
goto err; goto err;
/* trim may relocate, so get the new fdo and fdsl pointer */ // use the embedded fcsl if possible
fdo = fellow_disk_obj_trim(fc, fcs); if (fco->fcsl_embed.lsegs >= fdsl->nsegs) {
fdsl = fellow_disk_obj_fdsl(fdo);
assert(PAOK(fdsl));
CHECK_OBJ_NOTNULL(fdsl, FELLOW_DISK_SEGLIST_MAGIC);
// the fco-embedded fcsl may or may not fit
if (fco->fcsl_embed.lsegs >= fdsl->nsegs)
fco->fcsl = &fco->fcsl_embed; fco->fcsl = &fco->fcsl_embed;
fco->fcsl_embed.lsegs = fdsl->nsegs;
}
else { else {
// dup fellow_cache_seglists_load() // dup fellow_cache_seglists_load()
fcsl_mem = buddy_alloc1_ptr_extent_wait(fc->membuddy, FEP_META, fcsl_mem = buddy_alloc1_ptr_extent_wait(fc->membuddy, FEP_META,
...@@ -5516,7 +5515,38 @@ struct objcore **ocp, uintptr_t priv2, unsigned crit) ...@@ -5516,7 +5515,38 @@ struct objcore **ocp, uintptr_t priv2, unsigned crit)
AN(fco->fcsl); AN(fco->fcsl);
fco->fcsl->fcsl_sz = fcsl_mem.size; fco->fcsl->fcsl_sz = fcsl_mem.size;
fcsl_mem = buddy_ptr_extent_nil; fcsl_mem = buddy_ptr_extent_nil;
fco->fcsl_embed.lsegs = 0;
}
/* can we fit the fdo?
*
* XXX: for the extra fcsl case above, we are wasting
* sizeof(struct fellow_cache_seglist)
*/
AN(fco->fco_mem.ptr);
AN(fco->fco_mem.size);
sz = fellow_cache_obj_size(fco);
assert(sz <= fco->fco_mem.size);
ptr = (char *)fco + sz;
assert(PAOK(ptr));
spc = fco->fco_mem.size - sz;
fdsl->lsegs = fdsl->nsegs;
sz = fellow_disk_obj_size(fdo, fdsl);
if (sz <= spc) {
memcpy(ptr, fdo, sz);
fdo = fcs->u.fco_fdo = (void *)ptr;
buddy_return1_ptr_extent(fc->membuddy, &fcs->alloc);
} }
else
fdo = fellow_disk_obj_trim(fc, fcs);
fdsl = fellow_disk_obj_fdsl(fdo);
assert(PAOK(fdsl));
CHECK_OBJ_NOTNULL(fdsl, FELLOW_DISK_SEGLIST_MAGIC);
// XXX load of folow-up seglists could be async // XXX load of folow-up seglists could be async
// should not be a common case though, we try to make the first // should not be a common case though, we try to make the first
...@@ -6657,7 +6687,7 @@ t_cache(const char *fn, unsigned chksum) ...@@ -6657,7 +6687,7 @@ t_cache(const char *fn, unsigned chksum)
DBGSZ(fellow_disk_seg); DBGSZ(fellow_disk_seg);
DBGSZ(fellow_disk_seglist); DBGSZ(fellow_disk_seglist);
DBG("FELLOW_DISK_SEGLIST_MAX_SEGS %zu", FELLOW_DISK_SEGLIST_MAX_SEGS); DBG("FELLOW_DISK_SEGLIST_MAX_SEGS %u", FELLOW_DISK_SEGLIST_MAX_SEGS);
assert(FELLOW_DISK_SEGLIST_MAX_SEGS <= UINT16_MAX); assert(FELLOW_DISK_SEGLIST_MAX_SEGS <= UINT16_MAX);
DBGSZ(fellow_disk_obj); DBGSZ(fellow_disk_obj);
......
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