161aeeb33SMatthew Dillon /*
261aeeb33SMatthew Dillon * Copyright (c) 2008 The DragonFly Project. All rights reserved.
361aeeb33SMatthew Dillon *
461aeeb33SMatthew Dillon * This code is derived from software contributed to The DragonFly Project
561aeeb33SMatthew Dillon * by Matthew Dillon <dillon@backplane.com>
661aeeb33SMatthew Dillon *
761aeeb33SMatthew Dillon * Redistribution and use in source and binary forms, with or without
861aeeb33SMatthew Dillon * modification, are permitted provided that the following conditions
961aeeb33SMatthew Dillon * are met:
1061aeeb33SMatthew Dillon *
1161aeeb33SMatthew Dillon * 1. Redistributions of source code must retain the above copyright
1261aeeb33SMatthew Dillon * notice, this list of conditions and the following disclaimer.
1361aeeb33SMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright
1461aeeb33SMatthew Dillon * notice, this list of conditions and the following disclaimer in
1561aeeb33SMatthew Dillon * the documentation and/or other materials provided with the
1661aeeb33SMatthew Dillon * distribution.
1761aeeb33SMatthew Dillon * 3. Neither the name of The DragonFly Project nor the names of its
1861aeeb33SMatthew Dillon * contributors may be used to endorse or promote products derived
1961aeeb33SMatthew Dillon * from this software without specific, prior written permission.
2061aeeb33SMatthew Dillon *
2161aeeb33SMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2261aeeb33SMatthew Dillon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2361aeeb33SMatthew Dillon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2461aeeb33SMatthew Dillon * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2561aeeb33SMatthew Dillon * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2661aeeb33SMatthew Dillon * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
2761aeeb33SMatthew Dillon * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2861aeeb33SMatthew Dillon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2961aeeb33SMatthew Dillon * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
3061aeeb33SMatthew Dillon * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
3161aeeb33SMatthew Dillon * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3261aeeb33SMatthew Dillon * SUCH DAMAGE.
3361aeeb33SMatthew Dillon *
34ac76a28dSMatthew Dillon * $DragonFly: src/sbin/hammer/cache.c,v 1.5 2008/05/16 18:39:03 dillon Exp $
3561aeeb33SMatthew Dillon */
3661aeeb33SMatthew Dillon
3761aeeb33SMatthew Dillon #include "hammer_util.h"
3861aeeb33SMatthew Dillon
3961aeeb33SMatthew Dillon static int CacheUse;
4062997e7bSTomohiro Kusumi static int CacheMax = HAMMER_BUFSIZE * 1024;
4161aeeb33SMatthew Dillon static TAILQ_HEAD(, cache_info) CacheList = TAILQ_HEAD_INITIALIZER(CacheList);
4261aeeb33SMatthew Dillon
4325ee129eSTomohiro Kusumi int
hammer_parse_cache_size(const char * arg)4425ee129eSTomohiro Kusumi hammer_parse_cache_size(const char *arg)
4525ee129eSTomohiro Kusumi {
4625ee129eSTomohiro Kusumi char *ptr;
4725ee129eSTomohiro Kusumi int size = strtol(arg, &ptr, 0);
4825ee129eSTomohiro Kusumi
4925ee129eSTomohiro Kusumi switch(*ptr) {
5025ee129eSTomohiro Kusumi case 'm':
5125ee129eSTomohiro Kusumi case 'M':
5225ee129eSTomohiro Kusumi size *= 1024;
5325ee129eSTomohiro Kusumi /* fall through */
5425ee129eSTomohiro Kusumi case 'k':
5525ee129eSTomohiro Kusumi case 'K':
5625ee129eSTomohiro Kusumi size *= 1024;
5725ee129eSTomohiro Kusumi ++ptr;
5825ee129eSTomohiro Kusumi break;
5925ee129eSTomohiro Kusumi case '\0':
6025ee129eSTomohiro Kusumi case ':':
6125ee129eSTomohiro Kusumi /* bytes if no suffix */
6225ee129eSTomohiro Kusumi break;
6325ee129eSTomohiro Kusumi default:
6425ee129eSTomohiro Kusumi return(-1);
6525ee129eSTomohiro Kusumi }
6625ee129eSTomohiro Kusumi
6725ee129eSTomohiro Kusumi if (*ptr == ':') {
6825ee129eSTomohiro Kusumi UseReadAhead = strtol(ptr + 1, NULL, 0);
6925ee129eSTomohiro Kusumi UseReadBehind = -UseReadAhead;
7025ee129eSTomohiro Kusumi }
7125ee129eSTomohiro Kusumi if (size < 1024 * 1024)
7225ee129eSTomohiro Kusumi size = 1024 * 1024;
7325ee129eSTomohiro Kusumi if (UseReadAhead < 0)
7425ee129eSTomohiro Kusumi return(-1);
7525ee129eSTomohiro Kusumi if (UseReadAhead * HAMMER_BUFSIZE / size / 16) {
7625ee129eSTomohiro Kusumi UseReadAhead = size / 16 / HAMMER_BUFSIZE;
7725ee129eSTomohiro Kusumi UseReadBehind = -UseReadAhead;
7825ee129eSTomohiro Kusumi }
7925ee129eSTomohiro Kusumi
806c7ae023STomohiro Kusumi CacheMax = size;
816c7ae023STomohiro Kusumi return(0);
820faa08a1SMatthew Dillon }
830faa08a1SMatthew Dillon
840faa08a1SMatthew Dillon void
hammer_cache_add(cache_info_t cache)85*78418745STomohiro Kusumi hammer_cache_add(cache_info_t cache)
8661aeeb33SMatthew Dillon {
87b46b99bfSMatthew Dillon TAILQ_INSERT_HEAD(&CacheList, cache, entry);
8861aeeb33SMatthew Dillon CacheUse += HAMMER_BUFSIZE;
8961aeeb33SMatthew Dillon }
9061aeeb33SMatthew Dillon
9161aeeb33SMatthew Dillon void
hammer_cache_del(cache_info_t cache)92*78418745STomohiro Kusumi hammer_cache_del(cache_info_t cache)
9361aeeb33SMatthew Dillon {
9461aeeb33SMatthew Dillon TAILQ_REMOVE(&CacheList, cache, entry);
9561aeeb33SMatthew Dillon CacheUse -= HAMMER_BUFSIZE;
9661aeeb33SMatthew Dillon }
9761aeeb33SMatthew Dillon
9861aeeb33SMatthew Dillon void
hammer_cache_used(cache_info_t cache)99*78418745STomohiro Kusumi hammer_cache_used(cache_info_t cache)
100b46b99bfSMatthew Dillon {
101b46b99bfSMatthew Dillon TAILQ_REMOVE(&CacheList, cache, entry);
102b46b99bfSMatthew Dillon TAILQ_INSERT_TAIL(&CacheList, cache, entry);
103b46b99bfSMatthew Dillon }
104b46b99bfSMatthew Dillon
105b46b99bfSMatthew Dillon void
hammer_cache_flush(void)10661aeeb33SMatthew Dillon hammer_cache_flush(void)
10761aeeb33SMatthew Dillon {
108*78418745STomohiro Kusumi cache_info_t cache;
109*78418745STomohiro Kusumi cache_info_t first = NULL;
110a7bdb8f3SMatthew Dillon int count = 0;
11161aeeb33SMatthew Dillon
112f254e677STomohiro Kusumi if (CacheUse >= CacheMax) {
11361aeeb33SMatthew Dillon while ((cache = TAILQ_FIRST(&CacheList)) != NULL) {
114281de955STomohiro Kusumi if (cache == first)
115281de955STomohiro Kusumi break; /* seen this ref'd before */
116281de955STomohiro Kusumi
11761aeeb33SMatthew Dillon if (cache->refs) {
118281de955STomohiro Kusumi if (first == NULL)
119281de955STomohiro Kusumi first = cache;
1201d05d4e0STomohiro Kusumi hammer_cache_used(cache);
121281de955STomohiro Kusumi count++;
12261aeeb33SMatthew Dillon continue;
12361aeeb33SMatthew Dillon }
124e827d884STomohiro Kusumi if (count >= (CacheUse / HAMMER_BUFSIZE)) {
12562997e7bSTomohiro Kusumi CacheMax += HAMMER_BUFSIZE * 512;
126281de955STomohiro Kusumi count = 0;
127a7bdb8f3SMatthew Dillon }
128281de955STomohiro Kusumi
12961aeeb33SMatthew Dillon cache->refs = 1;
13061aeeb33SMatthew Dillon cache->delete = 1;
131c17fa600STomohiro Kusumi rel_buffer((buffer_info_t)cache);
13261aeeb33SMatthew Dillon
133281de955STomohiro Kusumi if (CacheUse < CacheMax / 2)
134a7bdb8f3SMatthew Dillon break;
13561aeeb33SMatthew Dillon }
13661aeeb33SMatthew Dillon }
137f254e677STomohiro Kusumi }
13861aeeb33SMatthew Dillon
139