X-Git-Url: http://git.vrable.net/?a=blobdiff_plain;f=bluesky%2Fcache.c;h=f3307d40f899b3c52ee329fc8b37c09a13b24e26;hb=e9bcb507c4e2ea94f38a9a947b620654d57bd6d0;hp=fd4797d82fa3844c110a2e80ee94d3b692305acb;hpb=1ff95dce46dcb5b0358db1fd4fa9698daeb326d7;p=bluesky.git diff --git a/bluesky/cache.c b/bluesky/cache.c index fd4797d..f3307d4 100644 --- a/bluesky/cache.c +++ b/bluesky/cache.c @@ -328,12 +328,14 @@ void bluesky_cachefile_gc(BlueSkyFS *fs) * then we'll just skip the file on this pass. */ if (g_mutex_trylock(cachefile->lock)) { int64_t age = bluesky_get_current_time() - cachefile->atime; - g_print("%s addr=%p mapcount=%d refcount=%d size=%d atime_age=%f", - cachefile->filename, cachefile->addr, cachefile->mapcount, - cachefile->refcount, cachefile->disk_used, age / 1e6); - if (cachefile->fetching) - g_print(" (fetching)"); - g_print("\n"); + if (bluesky_verbose) { + g_print("%s addr=%p mapcount=%d refcount=%d size=%d atime_age=%f", + cachefile->filename, cachefile->addr, cachefile->mapcount, + cachefile->refcount, cachefile->disk_used, age / 1e6); + if (cachefile->fetching) + g_print(" (fetching)"); + g_print("\n"); + } gboolean deletion_candidate = FALSE; if (g_atomic_int_get(&fs->log->disk_used) @@ -353,7 +355,9 @@ void bluesky_cachefile_gc(BlueSkyFS *fs) } if (deletion_candidate) { - g_print(" ...deleting\n"); + if (bluesky_verbose) { + g_print(" ...deleting\n"); + } if (unlinkat(fs->log->dirfd, cachefile->filename, 0) < 0) { fprintf(stderr, "Unable to unlink journal %s: %m\n", cachefile->filename); @@ -362,6 +366,8 @@ void bluesky_cachefile_gc(BlueSkyFS *fs) g_atomic_int_add(&fs->log->disk_used, -cachefile->disk_used); g_hash_table_remove(fs->log->mmap_cache, cachefile->filename); bluesky_rangeset_free(cachefile->items); + if (cachefile->prefetches != NULL) + bluesky_rangeset_free(cachefile->prefetches); g_mutex_unlock(cachefile->lock); g_mutex_free(cachefile->lock); g_cond_free(cachefile->cond); @@ -415,9 +421,50 @@ void bluesky_flushd_invoke(BlueSkyFS *fs) g_thread_create((GThreadFunc)flushd_task, fs, FALSE, NULL); } -void bluesky_flushd_invoke_conditional(BlueSkyFS *fs) +/* How urgent is flushing out data? Returns one of several values: + * 0 - memory state is fine + * 1 - should launch flushd if not already running + * 2 - should block writers until memory frees up + */ +static int compute_pressure(BlueSkyFS *fs) { + /* LEVEL 2 */ + /* Too much dirty data in memory? */ + if (g_atomic_int_get(&fs->cache_dirty) + + g_atomic_int_get(&fs->cache_log_dirty) + > bluesky_watermark_high_dirty) + return 2; + + /* Too much uncommitted data in the journal on disk, not yet flushed to the + * cloud? */ + /*printf("Dirty journals: %d to %d\n", + fs->log->journal_watermark, fs->log->seq_num);*/ + int dirty_limit; + dirty_limit = bluesky_options.cache_size / (LOG_SEGMENT_SIZE / 1024) / 2; + int dirty_journals = fs->log->seq_num - fs->log->journal_watermark + 1; + if (dirty_journals > 1 && dirty_journals >= dirty_limit) { + printf("Too many dirty journals (%d >= %d)\n", + dirty_journals, dirty_limit); + return 2; + } + + /* LEVEL 1 */ if (g_atomic_int_get(&fs->cache_dirty) < bluesky_watermark_medium_dirty) + return 1; + + if (dirty_journals > 1 && dirty_journals > dirty_limit / 2) { + printf("Many dirty journals (%d), should start writeback\n", + dirty_journals); + return 1; + } + + return 0; +} + +void bluesky_flushd_invoke_conditional(BlueSkyFS *fs) +{ + int pressure = compute_pressure(fs); + if (pressure == 0) return; if (bluesky_verbose) { @@ -430,16 +477,17 @@ void bluesky_flushd_invoke_conditional(BlueSkyFS *fs) /* If the system is under heavy memory pressure, actually delay execution * so the flush daemon can catch up. */ - while (g_atomic_int_get(&fs->cache_dirty) - + g_atomic_int_get(&fs->cache_log_dirty) - > bluesky_watermark_high_dirty) { + while (pressure > 1) { g_log("bluesky/flushd", G_LOG_LEVEL_DEBUG, "Waiting due to memory pressure, dirty=%d + %d", g_atomic_int_get(&fs->cache_dirty), g_atomic_int_get(&fs->cache_log_dirty)); g_mutex_lock(fs->lock); - g_cond_wait(fs->flushd_cond, fs->lock); + pressure = compute_pressure(fs); + if (pressure > 1) + g_cond_wait(fs->flushd_cond, fs->lock); g_mutex_unlock(fs->lock); + pressure = compute_pressure(fs); } }