mirror of
https://github.com/schoebel/mars
synced 2025-04-11 03:51:40 +00:00
improve cache footprint of MARS
This commit is contained in:
parent
2e923f145e
commit
d5cb69b391
17
Kconfig
17
Kconfig
@ -99,6 +99,23 @@ config MARS_LOADAVG_LIMIT
|
|||||||
---help---
|
---help---
|
||||||
Normally ON.
|
Normally ON.
|
||||||
|
|
||||||
|
config MARS_LINEAR_CACHE_SIZE
|
||||||
|
int "cache size for linear scans of logfiles (in MB)"
|
||||||
|
depends on MARS
|
||||||
|
default 64
|
||||||
|
---help---
|
||||||
|
Setting this to high numbers (or disabling by setting to 0)
|
||||||
|
may disturb the application performance, because MARS will
|
||||||
|
pollute the page cache with pages from the MARS logfiles.
|
||||||
|
Setting this to low numbers will prevent such a pollution,
|
||||||
|
at the cost of (sometimes) more IO operations.
|
||||||
|
EXCEPTION: when you run MARS on a standalone storage server
|
||||||
|
(e.g. exporting devices via iSCSI), you should use high numbers
|
||||||
|
here or even disable this feature. THEN (and ONLY THEN)
|
||||||
|
you want MARS to use all the memory for its own caching,
|
||||||
|
since there is no other application competing for main memory.
|
||||||
|
In unsure, take the default of 64.
|
||||||
|
|
||||||
#config MARS_HUNG
|
#config MARS_HUNG
|
||||||
# bool "hangup on kernel stacktrace (EXPERIMENTAL!!!)"
|
# bool "hangup on kernel stacktrace (EXPERIMENTAL!!!)"
|
||||||
# depends on MARS && MARS_BIGMODULE!=m
|
# depends on MARS && MARS_BIGMODULE!=m
|
||||||
|
61
mars_aio.c
61
mars_aio.c
@ -669,6 +669,50 @@ void fd_uninstall(unsigned int fd)
|
|||||||
EXPORT_SYMBOL(fd_uninstall);
|
EXPORT_SYMBOL(fd_uninstall);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static
|
||||||
|
void _mapfree_pages(struct aio_output *output, bool force)
|
||||||
|
{
|
||||||
|
struct aio_brick *brick = output->brick;
|
||||||
|
struct address_space *mapping;
|
||||||
|
pgoff_t start;
|
||||||
|
pgoff_t end;
|
||||||
|
pgoff_t gap;
|
||||||
|
|
||||||
|
if (brick->linear_cache_size <= 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (!force && ++output->rounds < brick->linear_cache_rounds)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (unlikely(!output->filp || !(mapping = output->filp->f_mapping)))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (unlikely(brick->linear_cache_rounds <= 0))
|
||||||
|
brick->linear_cache_rounds = 1024;
|
||||||
|
|
||||||
|
if (force) {
|
||||||
|
start = 0;
|
||||||
|
end = -1;
|
||||||
|
} else {
|
||||||
|
gap = brick->linear_cache_size * (1024 * 1024 / PAGE_SIZE);
|
||||||
|
end = output->min_pos / PAGE_SIZE - gap;
|
||||||
|
if (end <= 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
start = end - gap * 4;
|
||||||
|
if (start < 0)
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
output->min_pos = 0;
|
||||||
|
output->rounds = 0;
|
||||||
|
atomic_inc(&output->total_mapfree_count);
|
||||||
|
|
||||||
|
invalidate_mapping_pages(mapping, start, end);
|
||||||
|
|
||||||
|
done:;
|
||||||
|
}
|
||||||
|
|
||||||
static int aio_submit_thread(void *data)
|
static int aio_submit_thread(void *data)
|
||||||
{
|
{
|
||||||
struct aio_threadinfo *tinfo = data;
|
struct aio_threadinfo *tinfo = data;
|
||||||
@ -718,6 +762,8 @@ static int aio_submit_thread(void *data)
|
|||||||
int sleeptime;
|
int sleeptime;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
_mapfree_pages(output, false);
|
||||||
|
|
||||||
wait_event_interruptible_timeout(
|
wait_event_interruptible_timeout(
|
||||||
tinfo->event,
|
tinfo->event,
|
||||||
kthread_should_stop() ||
|
kthread_should_stop() ||
|
||||||
@ -729,8 +775,14 @@ static int aio_submit_thread(void *data)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for reads exactly at EOF (special case)
|
|
||||||
mref = mref_a->object;
|
mref = mref_a->object;
|
||||||
|
err = -EINVAL;
|
||||||
|
CHECK_PTR(mref, err);
|
||||||
|
|
||||||
|
if (!output->min_pos || mref->ref_pos < output->min_pos)
|
||||||
|
output->min_pos = mref->ref_pos;
|
||||||
|
|
||||||
|
// check for reads exactly at EOF (special case)
|
||||||
if (mref->ref_pos == mref->ref_total_size &&
|
if (mref->ref_pos == mref->ref_total_size &&
|
||||||
!mref->ref_rw &&
|
!mref->ref_rw &&
|
||||||
mref->ref_timeout > 0) {
|
mref->ref_timeout > 0) {
|
||||||
@ -786,6 +838,7 @@ static int aio_submit_thread(void *data)
|
|||||||
sleeptime += 1000 / HZ;
|
sleeptime += 1000 / HZ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
err:
|
||||||
if (unlikely(err < 0)) {
|
if (unlikely(err < 0)) {
|
||||||
_complete(output, mref, err);
|
_complete(output, mref, err);
|
||||||
}
|
}
|
||||||
@ -856,7 +909,8 @@ char *aio_statistics(struct aio_brick *brick, int verbose)
|
|||||||
"delays = %d "
|
"delays = %d "
|
||||||
"msleeps = %d "
|
"msleeps = %d "
|
||||||
"fdsyncs = %d "
|
"fdsyncs = %d "
|
||||||
"fdsync_waits = %d | "
|
"fdsync_waits = %d "
|
||||||
|
"map_free = %d | "
|
||||||
"flying reads = %d "
|
"flying reads = %d "
|
||||||
"writes = %d "
|
"writes = %d "
|
||||||
"allocs = %d "
|
"allocs = %d "
|
||||||
@ -871,6 +925,7 @@ char *aio_statistics(struct aio_brick *brick, int verbose)
|
|||||||
atomic_read(&output->total_msleep_count),
|
atomic_read(&output->total_msleep_count),
|
||||||
atomic_read(&output->total_fdsync_count),
|
atomic_read(&output->total_fdsync_count),
|
||||||
atomic_read(&output->total_fdsync_wait_count),
|
atomic_read(&output->total_fdsync_wait_count),
|
||||||
|
atomic_read(&output->total_mapfree_count),
|
||||||
atomic_read(&output->read_count),
|
atomic_read(&output->read_count),
|
||||||
atomic_read(&output->write_count),
|
atomic_read(&output->write_count),
|
||||||
atomic_read(&output->alloc_count),
|
atomic_read(&output->alloc_count),
|
||||||
@ -900,6 +955,7 @@ void aio_reset_statistics(struct aio_brick *brick)
|
|||||||
atomic_set(&output->total_msleep_count, 0);
|
atomic_set(&output->total_msleep_count, 0);
|
||||||
atomic_set(&output->total_fdsync_count, 0);
|
atomic_set(&output->total_fdsync_count, 0);
|
||||||
atomic_set(&output->total_fdsync_wait_count, 0);
|
atomic_set(&output->total_fdsync_wait_count, 0);
|
||||||
|
atomic_set(&output->total_mapfree_count, 0);
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
struct aio_threadinfo *tinfo = &output->tinfo[i];
|
struct aio_threadinfo *tinfo = &output->tinfo[i];
|
||||||
atomic_set(&tinfo->total_enqueue_count, 0);
|
atomic_set(&tinfo->total_enqueue_count, 0);
|
||||||
@ -1008,6 +1064,7 @@ cleanup:
|
|||||||
|
|
||||||
if (brick->power.led_off) {
|
if (brick->power.led_off) {
|
||||||
if (output->filp) {
|
if (output->filp) {
|
||||||
|
_mapfree_pages(output, true);
|
||||||
filp_close(output->filp, NULL);
|
filp_close(output->filp, NULL);
|
||||||
output->filp = NULL;
|
output->filp = NULL;
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,8 @@ struct aio_brick {
|
|||||||
MARS_BRICK(aio);
|
MARS_BRICK(aio);
|
||||||
// parameters
|
// parameters
|
||||||
int readahead;
|
int readahead;
|
||||||
|
int linear_cache_size; // in MB
|
||||||
|
int linear_cache_rounds;
|
||||||
bool o_direct;
|
bool o_direct;
|
||||||
bool o_fdsync;
|
bool o_fdsync;
|
||||||
bool wait_during_fdsync;
|
bool wait_during_fdsync;
|
||||||
@ -59,6 +61,8 @@ struct aio_output {
|
|||||||
// private
|
// private
|
||||||
struct file *filp;
|
struct file *filp;
|
||||||
int fd; // FIXME: remove this!
|
int fd; // FIXME: remove this!
|
||||||
|
int rounds;
|
||||||
|
loff_t min_pos;
|
||||||
struct aio_threadinfo tinfo[3];
|
struct aio_threadinfo tinfo[3];
|
||||||
aio_context_t ctxp;
|
aio_context_t ctxp;
|
||||||
wait_queue_head_t fdsync_event;
|
wait_queue_head_t fdsync_event;
|
||||||
@ -71,6 +75,7 @@ struct aio_output {
|
|||||||
atomic_t total_msleep_count;
|
atomic_t total_msleep_count;
|
||||||
atomic_t total_fdsync_count;
|
atomic_t total_fdsync_count;
|
||||||
atomic_t total_fdsync_wait_count;
|
atomic_t total_fdsync_wait_count;
|
||||||
|
atomic_t total_mapfree_count;
|
||||||
atomic_t read_count;
|
atomic_t read_count;
|
||||||
atomic_t write_count;
|
atomic_t write_count;
|
||||||
atomic_t alloc_count;
|
atomic_t alloc_count;
|
||||||
|
@ -13,6 +13,9 @@
|
|||||||
|
|
||||||
#define _STRATEGY
|
#define _STRATEGY
|
||||||
#include "mars.h"
|
#include "mars.h"
|
||||||
|
#include "mars_bio.h"
|
||||||
|
#include "mars_aio.h"
|
||||||
|
#include "mars_sio.h"
|
||||||
|
|
||||||
///////////////////////// own type definitions ////////////////////////
|
///////////////////////// own type definitions ////////////////////////
|
||||||
|
|
||||||
@ -202,6 +205,63 @@ void _clean_list(struct server_brick *brick, struct list_head *start)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int _set_server_sio_params(struct mars_brick *_brick, void *private)
|
||||||
|
{
|
||||||
|
struct sio_brick *sio_brick = (void*)_brick;
|
||||||
|
if (_brick->type != (void*)_sio_brick_type) {
|
||||||
|
MARS_ERR("bad brick type\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
sio_brick->o_direct = false;
|
||||||
|
sio_brick->o_fdsync = false;
|
||||||
|
MARS_INF("name = '%s' path = '%s'\n", _brick->brick_name, _brick->brick_path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int _set_server_aio_params(struct mars_brick *_brick, void *private)
|
||||||
|
{
|
||||||
|
struct aio_brick *aio_brick = (void*)_brick;
|
||||||
|
if (_brick->type == (void*)_sio_brick_type) {
|
||||||
|
return _set_server_sio_params(_brick, private);
|
||||||
|
}
|
||||||
|
if (_brick->type != (void*)_aio_brick_type) {
|
||||||
|
MARS_ERR("bad brick type\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
aio_brick->readahead = 1;
|
||||||
|
aio_brick->linear_cache_size = CONFIG_MARS_LINEAR_CACHE_SIZE;
|
||||||
|
aio_brick->o_direct = false;
|
||||||
|
aio_brick->o_fdsync = false;
|
||||||
|
aio_brick->wait_during_fdsync = false;
|
||||||
|
MARS_INF("name = '%s' path = '%s'\n", _brick->brick_name, _brick->brick_path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int _set_server_bio_params(struct mars_brick *_brick, void *private)
|
||||||
|
{
|
||||||
|
struct bio_brick *bio_brick;
|
||||||
|
if (_brick->type == (void*)_aio_brick_type) {
|
||||||
|
return _set_server_aio_params(_brick, private);
|
||||||
|
}
|
||||||
|
if (_brick->type == (void*)_sio_brick_type) {
|
||||||
|
return _set_server_sio_params(_brick, private);
|
||||||
|
}
|
||||||
|
if (_brick->type != (void*)_bio_brick_type) {
|
||||||
|
MARS_ERR("bad brick type\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
bio_brick = (void*)_brick;
|
||||||
|
bio_brick->ra_pages = 1;
|
||||||
|
bio_brick->do_noidle = true;
|
||||||
|
bio_brick->do_sync = true;
|
||||||
|
bio_brick->do_unplug = true;
|
||||||
|
MARS_INF("name = '%s' path = '%s'\n", _brick->brick_name, _brick->brick_path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
struct task_struct *_grab_handler(struct server_brick *brick)
|
struct task_struct *_grab_handler(struct server_brick *brick)
|
||||||
{
|
{
|
||||||
@ -299,7 +359,7 @@ int handler_thread(void *data)
|
|||||||
mars_global,
|
mars_global,
|
||||||
NULL,
|
NULL,
|
||||||
true,
|
true,
|
||||||
NULL,
|
_set_server_bio_params,
|
||||||
NULL,
|
NULL,
|
||||||
10 * HZ,
|
10 * HZ,
|
||||||
path,
|
path,
|
||||||
|
@ -247,6 +247,18 @@ int _set_aio_params(struct mars_brick *_brick, void *private)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int _set_aio_params_nocache(struct mars_brick *_brick, void *private)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
res = _set_aio_params(_brick, private);
|
||||||
|
if (_brick->type == (void*)&aio_brick_type) {
|
||||||
|
struct aio_brick *aio_brick = (void*)_brick;
|
||||||
|
aio_brick->linear_cache_size = CONFIG_MARS_LINEAR_CACHE_SIZE;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int _set_bio_params(struct mars_brick *_brick, void *private)
|
int _set_bio_params(struct mars_brick *_brick, void *private)
|
||||||
{
|
{
|
||||||
@ -274,6 +286,16 @@ int _set_bio_params(struct mars_brick *_brick, void *private)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static
|
||||||
|
int _set_bio_params_nocache(struct mars_brick *_brick, void *private)
|
||||||
|
{
|
||||||
|
if (_brick->type == (void*)&aio_brick_type) {
|
||||||
|
return _set_aio_params_nocache(_brick, private);
|
||||||
|
}
|
||||||
|
return _set_bio_params(_brick, private);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
int _set_if_params(struct mars_brick *_brick, void *private)
|
int _set_if_params(struct mars_brick *_brick, void *private)
|
||||||
{
|
{
|
||||||
@ -655,7 +677,7 @@ int __make_copy(
|
|||||||
make_brick_all(global,
|
make_brick_all(global,
|
||||||
NULL,
|
NULL,
|
||||||
false,
|
false,
|
||||||
_set_bio_params,
|
_set_bio_params_nocache,
|
||||||
NULL,
|
NULL,
|
||||||
10 * HZ,
|
10 * HZ,
|
||||||
NULL,
|
NULL,
|
||||||
@ -1690,7 +1712,7 @@ int make_log_init(void *buf, struct mars_dent *dent)
|
|||||||
make_brick_all(global,
|
make_brick_all(global,
|
||||||
aio_dent,
|
aio_dent,
|
||||||
false,
|
false,
|
||||||
_set_aio_params,
|
_set_aio_params_nocache,
|
||||||
NULL,
|
NULL,
|
||||||
10 * HZ,
|
10 * HZ,
|
||||||
aio_path,
|
aio_path,
|
||||||
|
Loading…
Reference in New Issue
Block a user