diff options
| -rw-r--r-- | tests/basic/cache.t | 69 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volume-set.c | 12 | ||||
| -rw-r--r-- | xlators/performance/io-cache/src/io-cache.c | 102 | ||||
| -rw-r--r-- | xlators/performance/io-cache/src/io-cache.h | 41 |
4 files changed, 208 insertions, 16 deletions
diff --git a/tests/basic/cache.t b/tests/basic/cache.t new file mode 100644 index 00000000000..92251732f4a --- /dev/null +++ b/tests/basic/cache.t @@ -0,0 +1,69 @@ +#!/bin/bash +# + +FILE=/var/log/glusterfs/samples/glusterfs_patchy.samp +rm $FILE + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +function print_cnt() { + local FOP_TYPE=$1 + local FOP_CNT=$(grep ,${FOP_TYPE} $FILE | wc -l) + echo $FOP_CNT +} + +function print_avg() { + local FOP_TYPE=$1 + local FILE=/var/log/glusterfs/samples/glusterfs_patchy.samp + local FOP_AVG=$(grep -oE "${FOP_TYPE},[0-9]+\." ${FILE} | grep -oE '[0-9]+' | awk 'NR == 1 { sum = 0 } { sum += $1; } END {printf "%d", sum/NR}') + echo $FOP_AVG +} + +cleanup; +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2} +TEST $CLI volume set $V0 nfs.disable off +TEST $CLI volume set $V0 diagnostics.latency-measurement on +TEST $CLI volume set $V0 diagnostics.count-fop-hits on +TEST $CLI volume set $V0 diagnostics.fop-sample-buf-size 65535 +TEST $CLI volume set $V0 diagnostics.fop-sample-interval 1 +TEST $CLI volume set $V0 diagnostics.stats-dump-interval 1 +TEST $CLI volume start $V0 +TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 + +for i in {1..100} +do + df $M0 &> /dev/null +done + +sleep 6 + +# Get average +STATFS_CNT0=$(print_cnt STATFS) +TEST [ "$STATFS_CNT0" -gt "0" ] +STATFS_AVG0=$(print_avg STATFS) +# Make it easier to compute averages +rm $FILE + +TEST $CLI volume set $V0 performance.nfs.io-cache on +TEST $CLI volume set $V0 performance.statfs-cache on +TEST $CLI volume set $V0 performance.statfs-cache-timeout 10 + +for i in {1..100} +do + df $M0 &> /dev/null +done + +sleep 6 + +# Get average +STATFS_CNT1=$(print_cnt STATFS) +TEST [ "$STATFS_CNT1" -eq "$STATFS_CNT0" ] +STATFS_AVG1=$(print_avg STATFS) + +# Verify that cached average * 10 is still faster than uncached +STATFS_AVG1x10=$(($STATFS_AVG1 * 10)) +TEST [ "$STATFS_AVG0" -gt "$STATFS_AVG1x10" ] +#cleanup diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c index 0f098646b30..20697aff6d4 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c @@ -1468,6 +1468,18 @@ struct volopt_map_entry glusterd_volopt_map[] = { .op_version = 1, .flags = OPT_FLAG_CLIENT_OPT }, + { .key = "performance.statfs-cache", + .voltype = "performance/io-cache", + .option = "statfs-cache", + .op_version = 1, + .flags = OPT_FLAG_CLIENT_OPT + }, + { .key = "performance.statfs-cache-timeout", + .voltype = "performance/io-cache", + .option = "statfs-cache-timeout", + .op_version = 1, + .flags = OPT_FLAG_CLIENT_OPT + }, /* IO-threads xlator options */ { .key = "performance.io-thread-count", diff --git a/xlators/performance/io-cache/src/io-cache.c b/xlators/performance/io-cache/src/io-cache.c index 98c37746921..f199b229bc2 100644 --- a/xlators/performance/io-cache/src/io-cache.c +++ b/xlators/performance/io-cache/src/io-cache.c @@ -1479,6 +1479,74 @@ ioc_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, return 0; } +int32_t +ioc_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + struct statvfs *buf, dict_t *xdata) +{ + ioc_table_t *table = NULL; + struct ioc_statvfs *cache = NULL; + + if (op_ret != 0) + goto out; + + table = this->private; + cache = &table->statfs_cache; + + LOCK (&cache->lock); + + gettimeofday (&cache->tv, NULL); + cache->buf = *buf; + + UNLOCK (&cache->lock); + +out: + STACK_UNWIND_STRICT (statfs, frame, op_ret, op_errno, buf, xdata); + return 0; +} + +int +ioc_statfs (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) +{ + ioc_table_t *table = NULL; + struct ioc_statvfs *cache = NULL; + struct statvfs buf; + struct timeval tv = {0,}; + + table = this->private; + cache = &table->statfs_cache; + + if (!cache->enabled) + goto disabled; + + gettimeofday (&tv, NULL); + + LOCK (&cache->lock); + + if (time_elapsed (&tv, &cache->tv) >= cache->timeout) { + UNLOCK (&cache->lock); + goto uncached; + } + + buf = cache->buf; + + UNLOCK (&cache->lock); + + STACK_UNWIND_STRICT (statfs, frame, 0, 0, &buf, xdata); + + return 0; + +disabled: + STACK_WIND_TAIL (frame, FIRST_CHILD (frame->this), + FIRST_CHILD (frame->this)->fops->statfs, loc, xdata); + return 0; + +uncached: + STACK_WIND (frame, ioc_statfs_cbk, + FIRST_CHILD (frame->this), + FIRST_CHILD (frame->this)->fops->statfs, loc, xdata); + return 0; +} int32_t ioc_get_priority_list (const char *opt_str, struct list_head *first) @@ -1696,6 +1764,13 @@ reconfigure (xlator_t *this, dict_t *options) } table->cache_size = cache_size_new; + GF_OPTION_RECONF ("statfs-cache", table->statfs_cache.enabled, + options, bool, unlock); + + GF_OPTION_RECONF ("statfs-cache-timeout", + table->statfs_cache.timeout, + options, int32, unlock); + ret = 0; } unlock: @@ -1755,6 +1830,10 @@ init (xlator_t *this) GF_OPTION_INIT ("max-file-size", table->max_file_size, size_uint64, out); + GF_OPTION_INIT ("statfs-cache", table->statfs_cache.enabled, bool, out); + + GF_OPTION_INIT ("statfs-cache-timeout", table->statfs_cache.timeout, int32, out); + if (!check_cache_size_ok (this, table->cache_size)) { ret = -1; goto out; @@ -1827,6 +1906,11 @@ init (xlator_t *this) ctx = this->ctx; ioc_log2_page_size = log_base2 (ctx->page_size); + LOCK_INIT (&table->statfs_cache.lock); + /* Invalidate statfs cache */ + table->statfs_cache.tv.tv_sec = 0; + table->statfs_cache.tv.tv_usec = 0; + out: if (ret == -1) { if (table != NULL) { @@ -2096,6 +2180,7 @@ fini (xlator_t *this) GF_ASSERT (list_empty (&table->inode_lru[i])); } + LOCK_DESTROY (&table->statfs_cache.lock); GF_ASSERT (list_empty (&table->inodes)); */ pthread_mutex_destroy (&table->table_lock); @@ -2120,6 +2205,7 @@ struct xlator_fops fops = { .readdirp = ioc_readdirp, .discard = ioc_discard, .zerofill = ioc_zerofill, + .statfs = ioc_statfs, }; @@ -2171,5 +2257,21 @@ struct volume_options options[] = { .description = "Maximum file size which would be cached by the " "io-cache translator." }, + { .key = {"statfs-cache"}, + .type = GF_OPTION_TYPE_BOOL, + .default_value = "0", + .description = "The cached statfs for a filesystem will be " + "till 'statfs-cache-timeout' seconds, after which re-validation " + "is performed." + }, + { .key = {"statfs-cache-timeout"}, + .type = GF_OPTION_TYPE_INT, + .min = 0, + .max = 60, + .default_value = "1", + .description = "The cached statfs for a filesystem will be " + "till 'statfs-cache-timeout' seconds, after which re-validation " + "is performed." + }, { .key = {NULL} }, }; diff --git a/xlators/performance/io-cache/src/io-cache.h b/xlators/performance/io-cache/src/io-cache.h index d7c823fe962..da71b2f2371 100644 --- a/xlators/performance/io-cache/src/io-cache.h +++ b/xlators/performance/io-cache/src/io-cache.h @@ -148,23 +148,32 @@ struct ioc_inode { inode_t *inode; }; +struct ioc_statvfs { + struct statvfs buf; + int32_t timeout; + struct timeval tv; + gf_boolean_t enabled; + gf_lock_t lock; +}; + struct ioc_table { - uint64_t page_size; - uint64_t cache_size; - uint64_t cache_used; - uint64_t min_file_size; - uint64_t max_file_size; - struct list_head inodes; /* list of inodes cached */ - struct list_head active; - struct list_head *inode_lru; - struct list_head priority_list; - int32_t readv_count; - pthread_mutex_t table_lock; - xlator_t *xl; - uint32_t inode_count; - int32_t cache_timeout; - int32_t max_pri; - struct mem_pool *mem_pool; + uint64_t page_size; + uint64_t cache_size; + uint64_t cache_used; + uint64_t min_file_size; + uint64_t max_file_size; + struct list_head inodes; /* list of inodes cached */ + struct list_head active; + struct list_head *inode_lru; + struct list_head priority_list; + int32_t readv_count; + pthread_mutex_t table_lock; + xlator_t *xl; + uint32_t inode_count; + int32_t cache_timeout; + int32_t max_pri; + struct mem_pool *mem_pool; + struct ioc_statvfs statfs_cache; }; typedef struct ioc_table ioc_table_t; |
