summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/basic/cache.t69
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volume-set.c12
-rw-r--r--xlators/performance/io-cache/src/io-cache.c102
-rw-r--r--xlators/performance/io-cache/src/io-cache.h41
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;