/cli/

> cgit logo index : glusterfs.git
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnand Avati <avati@redhat.com>2013-01-18 14:04:23 -0800
committerAnand Avati <avati@redhat.com>2013-01-28 12:35:57 -0800
commitcc96adbe4604ea5fd462d8db77486c2f963baf43 (patch)
tree40d5ea5d0e04539c3413f38481d9b9854d52b6c4
parent99e63168c498cf57f3f8fabab1d2b86a4ea639ce (diff)
quick-read: refactor
- peel out 'open behind' functionality into a separate translator - issue where, if file size had grown by revalidate, data was not flushed - removed unnecessary acquistion of table->lock (e.g in qr_lookup()) - keep inode ctx persistent, prune only data (effectively changing the order of lock acquisition from INODE -> TABLE) - validation with readdirplus - use variable size iobufs to simply cached reads Change-Id: If1586d0298fd1697ddff9fd7008efb3d286d436a BUG: 846240 Signed-off-by: Anand Avati <avati@redhat.com> Reviewed-on: http://review.gluster.org/4403 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Jeff Darcy <jdarcy@redhat.com>
Diffstat
-rw-r--r--tests/performance/quick-read.t45
-rw-r--r--xlators/performance/quick-read/src/quick-read-mem-types.h1
-rw-r--r--xlators/performance/quick-read/src/quick-read.c3695
-rw-r--r--xlators/performance/quick-read/src/quick-read.h57
4 files changed, 458 insertions, 3340 deletions
diff --git a/tests/performance/quick-read.t b/tests/performance/quick-read.t
new file mode 100644
index 00000000000..84bb7e66b3f
--- /dev/null
+++ b/tests/performance/quick-read.t
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+. $(dirname $0)/../include.rc
+
+cleanup;
+
+TEST glusterd
+TEST pidof glusterd
+TEST $CLI volume info;
+
+TEST $CLI volume create $V0 $H0:$B0/${V0}{1,2};
+
+TEST $CLI volume start $V0;
+
+## Mount FUSE
+TEST glusterfs -s $H0 --volfile-id $V0 $M0;
+
+TEST glusterfs -s $H0 --volfile-id $V0 $M1;
+
+D0="hello-this-is-a-test-message0";
+F0="test-file0";
+
+function write_to()
+{
+ local file="$1";
+ local data="$2";
+
+ echo "$data" > "$file";
+}
+
+
+TEST write_to "$M0/$F0" "$D0";
+EXPECT "$D0" cat $M1/$F0;
+
+TEST $CLI volume set $V0 performance.quick-read off;
+
+D1="hello-this-is-a-test-message1";
+F1="test-file1";
+
+TEST write_to "$M0/$F1" "$D1";
+EXPECT "$D1" cat $M1/$F1;
+
+EXPECT "$D0" cat $M1/$F0;
+
+cleanup;
diff --git a/xlators/performance/quick-read/src/quick-read-mem-types.h b/xlators/performance/quick-read/src/quick-read-mem-types.h
index 73c87c819d0..78547f64116 100644
--- a/xlators/performance/quick-read/src/quick-read-mem-types.h
+++ b/xlators/performance/quick-read/src/quick-read-mem-types.h
@@ -15,6 +15,7 @@
enum gf_qr_mem_types_ {
gf_qr_mt_qr_inode_t = gf_common_mt_end + 1,
+ gf_qr_mt_content_t,
gf_qr_mt_qr_fd_ctx_t,
gf_qr_mt_iovec,
gf_qr_mt_qr_conf_t,
diff --git a/xlators/performance/quick-read/src/quick-read.c b/xlators/performance/quick-read/src/quick-read.c
index 867900b902c..34e27138f26 100644
--- a/xlators/performance/quick-read/src/quick-read.c
+++ b/xlators/performance/quick-read/src/quick-read.c
@@ -11,182 +11,102 @@
#include "quick-read.h"
#include "statedump.h"
-#define QR_DEFAULT_CACHE_SIZE 134217728
+qr_inode_t *qr_inode_ctx_get (xlator_t *this, inode_t *inode);
+void __qr_inode_prune (qr_inode_table_t *table, qr_inode_t *qr_inode);
-struct volume_options options[];
-void
-_fd_unref (fd_t *fd);
-
-void
-qr_local_free (qr_local_t *local)
+int
+__qr_inode_ctx_set (xlator_t *this, inode_t *inode, qr_inode_t *qr_inode)
{
- if (local == NULL) {
- goto out;
- }
-
- if (local->stub != NULL) {
- call_stub_destroy (local->stub);
- }
+ uint64_t value = 0;
+ int ret = -1;
- GF_FREE (local->path);
+ value = (long) qr_inode;
- mem_put (local);
+ ret = __inode_ctx_set (inode, this, &value);
-out:
- return;
+ return ret;
}
-qr_local_t *
-qr_local_new (xlator_t *this)
-{
- qr_local_t *local = NULL;
-
- local = mem_get0 (this->local_pool);
- if (local == NULL) {
- goto out;
- }
-
- LOCK_INIT (&local->lock);
- INIT_LIST_HEAD (&local->list);
-out:
- return local;
-}
-
-
-int32_t
-qr_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size,
- off_t offset, uint32_t flags, dict_t *xdata);
-
-
-static void
-qr_loc_wipe (loc_t *loc)
+qr_inode_t *
+__qr_inode_ctx_get (xlator_t *this, inode_t *inode)
{
- if (loc == NULL) {
- goto out;
- }
+ qr_inode_t *qr_inode = NULL;
+ uint64_t value = 0;
+ int ret = -1;
- if (loc->path) {
- GF_FREE ((char *)loc->path);
- loc->path = NULL;
- }
+ ret = __inode_ctx_get (inode, this, &value);
+ if (ret)
+ return NULL;
- if (loc->inode) {
- inode_unref (loc->inode);
- loc->inode = NULL;
- }
-
- if (loc->parent) {
- inode_unref (loc->parent);
- loc->parent = NULL;
- }
+ qr_inode = (void *) ((long) value);
-out:
- return;
+ return qr_inode;
}
-static int32_t
-qr_loc_fill (loc_t *loc, inode_t *inode, char *path)
+qr_inode_t *
+qr_inode_ctx_get (xlator_t *this, inode_t *inode)
{
- int32_t ret = -1;
-
- GF_VALIDATE_OR_GOTO_WITH_ERROR ("quick-read", loc, out, errno, EINVAL);
- GF_VALIDATE_OR_GOTO_WITH_ERROR ("quick-read", inode, out, errno,
- EINVAL);
- GF_VALIDATE_OR_GOTO_WITH_ERROR ("quick-read", path, out, errno, EINVAL);
-
- loc->inode = inode_ref (inode);
- uuid_copy (loc->gfid, inode->gfid);
+ qr_inode_t *qr_inode = NULL;
- loc->path = gf_strdup (path);
- if (!loc->path)
- goto out;
-
- ret = 0;
-out:
- if (ret == -1) {
- qr_loc_wipe (loc);
- }
+ LOCK (&inode->lock);
+ {
+ qr_inode = __qr_inode_ctx_get (this, inode);
+ }
+ UNLOCK (&inode->lock);
- return ret;
+ return qr_inode;
}
-void
-qr_resume_pending_ops (qr_fd_ctx_t *qr_fd_ctx, int32_t op_ret, int32_t op_errno)
+qr_inode_t *
+qr_inode_new (xlator_t *this, inode_t *inode)
{
- call_stub_t *stub = NULL, *tmp = NULL;
- struct list_head waiting_ops = {0, };
-
- GF_VALIDATE_OR_GOTO ("quick-read", qr_fd_ctx, out);
-
- INIT_LIST_HEAD (&waiting_ops);
-
- LOCK (&qr_fd_ctx->lock);
- {
- qr_fd_ctx->open_in_transit = 0;
- list_splice_init (&qr_fd_ctx->waiting_ops,
- &waiting_ops);
- }
- UNLOCK (&qr_fd_ctx->lock);
+ qr_inode_t *qr_inode = NULL;
- if (!list_empty (&waiting_ops)) {
- list_for_each_entry_safe (stub, tmp, &waiting_ops, list) {
- list_del_init (&stub->list);
- if (op_ret < 0) {
- qr_local_t *local = NULL;
+ qr_inode = GF_CALLOC (1, sizeof (*qr_inode), gf_qr_mt_qr_inode_t);
+ if (!qr_inode)
+ return NULL;
- local = stub->frame->local;
- local->op_ret = op_ret;
- local->op_errno = op_errno;
- }
+ INIT_LIST_HEAD (&qr_inode->lru);
- call_resume (stub);
- }
- }
+ qr_inode->priority = 0; /* initial priority */
-out:
- return;
+ return qr_inode;
}
-static void
-qr_fd_ctx_free (qr_fd_ctx_t *qr_fd_ctx)
+qr_inode_t *
+qr_inode_ctx_get_or_new (xlator_t *this, inode_t *inode)
{
- GF_VALIDATE_OR_GOTO ("quick-read", qr_fd_ctx, out);
+ qr_inode_t *qr_inode = NULL;
+ int ret = -1;
+ qr_private_t *priv = NULL;
- GF_ASSERT (list_empty (&qr_fd_ctx->waiting_ops));
+ priv = this->private;
- LOCK (&qr_fd_ctx->fd->inode->lock);
- {
- list_del_init (&qr_fd_ctx->inode_list);
- }
- UNLOCK (&qr_fd_ctx->fd->inode->lock);
-
- GF_FREE (qr_fd_ctx->path);
- GF_FREE (qr_fd_ctx);
-
-out:
- return;
-}
-
-
-static inline uint32_t
-is_match (const char *path, const char *pattern)
-{
- int32_t ret = 0;
- uint32_t match = 0;
+ LOCK (&inode->lock);
+ {
+ qr_inode = __qr_inode_ctx_get (this, inode);
+ if (qr_inode)
+ goto unlock;
- GF_VALIDATE_OR_GOTO ("quick-read", path, out);
- GF_VALIDATE_OR_GOTO ("quick-read", pattern, out);
+ qr_inode = qr_inode_new (this, inode);
+ if (!qr_inode)
+ goto unlock;
- ret = fnmatch (pattern, path, FNM_NOESCAPE);
- match = (ret == 0);
+ ret = __qr_inode_ctx_set (this, inode, qr_inode);
+ if (ret) {
+ __qr_inode_prune (&priv->table, qr_inode);
+ GF_FREE (qr_inode);
+ }
+ }
+unlock:
+ UNLOCK (&inode->lock);
-out:
- return match;
+ return qr_inode;
}
@@ -196,3230 +116,527 @@ qr_get_priority (qr_conf_t *conf, const char *path)
uint32_t priority = 0;
struct qr_priority *curr = NULL;
- GF_VALIDATE_OR_GOTO ("quick-read", conf, out);
- GF_VALIDATE_OR_GOTO ("quick-read", path, out);
-
list_for_each_entry (curr, &conf->priority_list, list) {
- if (is_match (path, curr->pattern))
+ if (fnmatch (curr->pattern, path, FNM_NOESCAPE) == 0)
priority = curr->priority;
}
-out:
return priority;
}
-/* To be called with this-priv->table.lock held */
-qr_inode_t *
-__qr_inode_alloc (xlator_t *this, char *path, inode_t *inode)
+void
+__qr_inode_register (qr_inode_table_t *table, qr_inode_t *qr_inode)
{
- qr_inode_t *qr_inode = NULL;
- qr_private_t *priv = NULL;
- int priority = 0;
-
- GF_VALIDATE_OR_GOTO ("quick-read", this, out);
- GF_VALIDATE_OR_GOTO (this->name, path, out);
- GF_VALIDATE_OR_GOTO (this->name, inode, out);
-
- priv = this->private;
- GF_VALIDATE_OR_GOTO (this->name, priv, out);
+ if (!qr_inode->data)
+ return;
- qr_inode = GF_CALLOC (1, sizeof (*qr_inode), gf_qr_mt_qr_inode_t);
- if (qr_inode == NULL) {
- goto out;
- }
+ if (list_empty (&qr_inode->lru))
+ /* first time addition of this qr_inode into table */
+ table->cache_used += qr_inode->size;
+ else
+ list_del_init (&qr_inode->lru);
- INIT_LIST_HEAD (&qr_inode->lru);
- INIT_LIST_HEAD (&qr_inode->fd_list);
-
- priority = qr_get_priority (&priv->conf, path);
-
- list_add_tail (&qr_inode->lru, &priv->table.lru[priority]);
-
- qr_inode->inode = inode;
- qr_inode->priority = priority;
-out:
- return qr_inode;
+ list_add_tail (&qr_inode->lru, &table->lru[qr_inode->priority]);
}
-/* To be called with qr_inode->table->lock held */
void
-__qr_inode_free (qr_inode_t *qr_inode)
+qr_inode_set_priority (xlator_t *this, inode_t *inode, const char *path)
{
- qr_fd_ctx_t *fdctx = NULL, *tmp_fdctx = NULL;
+ uint32_t priority = 0;
+ qr_inode_table_t *table = NULL;
+ qr_inode_t *qr_inode = NULL;
+ qr_private_t *priv = NULL;
+ qr_conf_t *conf = NULL;
- GF_VALIDATE_OR_GOTO ("quick-read", qr_inode, out);
+ qr_inode = qr_inode_ctx_get (this, inode);
+ if (!qr_inode)
+ return;
- if (qr_inode->xattr) {
- dict_unref (qr_inode->xattr);
- }
+ priv = this->private;
+ table = &priv->table;
+ conf = &priv->conf;
- list_del (&qr_inode->lru);
+ if (path)
+ priority = qr_get_priority (conf, path);
+ else
+ /* retain existing priority, just bump LRU */
+ priority = qr_inode->priority;
- LOCK (&qr_inode->inode->lock);
- {
- list_for_each_entry_safe (fdctx, tmp_fdctx, &qr_inode->fd_list,
- inode_list) {
- list_del_init (&fdctx->inode_list);
- }
- }
- UNLOCK (&qr_inode->inode->lock);
+ LOCK (&table->lock);
+ {
+ qr_inode->priority = priority;
- GF_FREE (qr_inode);
-out:
- return;
+ __qr_inode_register (table, qr_inode);
+ }
+ UNLOCK (&table->lock);
}
+
/* To be called with priv->table.lock held */
void
-__qr_cache_prune (xlator_t *this)
-{
- qr_private_t *priv = NULL;
- qr_conf_t *conf = NULL;
- qr_inode_table_t *table = NULL;
- qr_inode_t *curr = NULL, *next = NULL;
- int32_t index = 0;
- uint64_t size_to_prune = 0;
- uint64_t size_pruned = 0;
-
- GF_VALIDATE_OR_GOTO ("quick-read", this, out);
- priv = this->private;
- GF_VALIDATE_OR_GOTO (this->name, priv, out);
-
- table = &priv->table;
- conf = &priv->conf;
-
- size_to_prune = table->cache_used - conf->cache_size;
-
- for (index=0; index < conf->max_pri; index++) {
- list_for_each_entry_safe (curr, next, &table->lru[index], lru) {
- size_pruned += curr->stbuf.ia_size;
- inode_ctx_del (curr->inode, this, NULL);
- __qr_inode_free (curr);
- if (size_pruned >= size_to_prune)
- goto done;
- }
- }
-
-done:
- table->cache_used -= size_pruned;
-
-out:
- return;
-}
-
-/* To be called with table->lock held */
-inline char
-__qr_need_cache_prune (qr_conf_t *conf, qr_inode_table_t *table)
+__qr_inode_prune (qr_inode_table_t *table, qr_inode_t *qr_inode)
{
- char need_prune = 0;
+ GF_FREE (qr_inode->data);
+ qr_inode->data = NULL;
- GF_VALIDATE_OR_GOTO ("quick-read", conf, out);
- GF_VALIDATE_OR_GOTO ("quick-read", table, out);
+ if (!list_empty (&qr_inode->lru)) {
+ table->cache_used -= qr_inode->size;
+ qr_inode->size = 0;
- need_prune = (table->cache_used > conf->cache_size);
+ list_del_init (&qr_inode->lru);
+ }
-out:
- return need_prune;
+ memset (&qr_inode->buf, 0, sizeof (qr_inode->buf));
}
-int32_t
-qr_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, inode_t *inode,
- struct iatt *buf, dict_t *xdata, struct iatt *postparent)
-{
- data_t *content = NULL;
- qr_inode_t *qr_inode = NULL;
- uint64_t value = 0;
- int ret = -1;
- qr_conf_t *conf = NULL;
- qr_inode_table_t *table = NULL;
- qr_private_t *priv = NULL;
- qr_local_t *local = NULL;
-
- GF_ASSERT (frame);
-
- if ((op_ret == -1) || (xdata == NULL)) {
- goto out;
- }
-
- if ((this == NULL) || (this->private == NULL)) {
- gf_log (frame->this->name, GF_LOG_WARNING,
- (this == NULL) ? "xlator object (this) is NULL"
- : "quick-read configuration is not found");
- op_ret = -1;
- op_errno = EINVAL;
- goto out;
- }
-
- priv = this->private;
- conf = &priv->conf;
- table = &priv->table;
-
- local = frame->local;
-
- if (buf->ia_size > conf->max_file_size) {
- goto out;
- }
-
- if (IA_ISDIR (buf->ia_type)) {
- goto out;
- }
-
- if (inode == NULL) {
- op_ret = -1;
- op_errno = EINVAL;
- gf_log (this->name, GF_LOG_WARNING,
- "lookup returned a NULL inode");
- goto out;
- }
-
- content = dict_get (xdata, GF_CONTENT_KEY);
- if (content == NULL) {
- goto out;
- }
-
- LOCK (&table->lock);
- {
- ret = inode_ctx_get (inode, this, &value);
- if (ret == -1) {
- qr_inode = __qr_inode_alloc (this, local->path, inode);
- if (qr_inode == NULL) {
- op_ret = -1;
- op_errno = ENOMEM;
- goto unlock;
- }
-
- ret = inode_ctx_put (inode, this,
- (uint64_t)(long)qr_inode);
- if (ret == -1) {
- __qr_inode_free (qr_inode);
- qr_inode = NULL;
- op_ret = -1;
- op_errno = EINVAL;
- gf_log (this->name, GF_LOG_WARNING,
- "cannot set quick-read context in "
- "inode (gfid:%s)",
- uuid_utoa (inode->gfid));
- goto unlock;
- }
- } else {
- qr_inode = (qr_inode_t *)(long)value;
- if (qr_inode == NULL) {
- op_ret = -1;
- op_errno = EINVAL;
- gf_log (this->name, GF_LOG_WARNING,
- "cannot find quick-read context in "
- "inode (gfid:%s)",
- uuid_utoa (inode->gfid));
- goto unlock;
- }
- }
-
- /*
- * Create our own internal dict and migrate the file content
- * over to it so it isn't floating around in other translator
- * caches.
- */
- if (qr_inode->xattr) {
- dict_unref (qr_inode->xattr);
- qr_inode->xattr = NULL;
- table->cache_used -= qr_inode->stbuf.ia_size;
- }
-
- qr_inode->xattr = dict_new();
- if (!qr_inode->xattr) {
- op_ret = -1;
- op_errno = ENOMEM;
- goto unlock;
- }
-
- if (dict_set(qr_inode->xattr, GF_CONTENT_KEY, content) < 0) {
- op_ret = -1;
- op_errno = ENOMEM;
- goto unlock;
- }
-
- dict_del(xdata, GF_CONTENT_KEY);
-
- qr_inode->stbuf = *buf;
- table->cache_used += buf->ia_size;
-
- gettimeofday (&qr_inode->tv, NULL);
- if (__qr_need_cache_prune (conf, table)) {
- __qr_cache_prune (this);
- }
- }
-unlock:
- UNLOCK (&table->lock);
-
-out:
- /*
- * FIXME: content size in dict can be greater than the size application
- * requested for. Applications need to be careful till this is fixed.
- */
- QR_STACK_UNWIND (lookup, frame, op_ret, op_errno, inode, buf, xdata,
- postparent);
-
- return 0;
-}
-
-
-int32_t
-qr_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc,
- dict_t *xdata)
+void
+qr_inode_prune (xlator_t *this, inode_t *inode)
{
- qr_conf_t *conf = NULL;
- dict_t *new_req_dict = NULL;
- int32_t op_ret = -1, op_errno = EINVAL;
- data_t *content = NULL;
- uint64_t requested_size = 0, size = 0, value = 0;
- char cached = 0;
- qr_inode_t *qr_inode = NULL;
- qr_private_t *priv = NULL;
- qr_inode_table_t *table = NULL;
- qr_local_t *local = NULL;
-
- GF_ASSERT (frame);
- GF_VALIDATE_OR_GOTO (frame->this->name, this, unwind);
- GF_VALIDATE_OR_GOTO (frame->this->name, loc, unwind);
-
- priv = this->private;
- GF_VALIDATE_OR_GOTO (frame->this->name, priv, unwind);
-
- conf = &priv->conf;
- if (conf == NULL) {
- op_ret = -1;
- op_errno = EINVAL;
- goto unwind;
- }
-
- table = &priv->table;
-
- local = qr_local_new (this);
- GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, local, unwind, op_errno,
- ENOMEM);
-
- frame->local = local;
-
- local->path = gf_strdup (loc->path);
- GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, local, unwind, op_errno,
- ENOMEM);
- LOCK (&table->lock);
- {
- op_ret = inode_ctx_get (loc->inode, this, &value);
- if (op_ret == 0) {
- qr_inode = (qr_inode_t *)(long)value;
- if (qr_inode != NULL) {
- if (qr_inode->xattr) {
- cached = 1;
- }
- }
- }
- }
- UNLOCK (&table->lock);
-
- if ((xdata == NULL) && (conf->max_file_size > 0)) {
- new_req_dict = xdata = dict_new ();
- if (xdata == NULL) {
- op_ret = -1;
- op_errno = ENOMEM;
- goto unwind;
- }
- }
-
- if (!cached) {
- if (xdata) {
- content = dict_get (xdata, GF_CONTENT_KEY);
- if (content) {
- requested_size = data_to_uint64 (content);
- }
- }
-
- if ((conf->max_file_size > 0)
- && (conf->max_file_size != requested_size)) {
- size = (conf->max_file_size > requested_size) ?
- conf->max_file_size : requested_size;
-
- op_ret = dict_set (xdata, GF_CONTENT_KEY,
- data_from_uint64 (size));
- if (op_ret < 0) {
- op_ret = -1;
- op_errno = ENOMEM;
- gf_log (this->name, GF_LOG_WARNING,
- "cannot set key in request dict to "
- "request file "
- "content during lookup cbk");
- goto unwind;
- }
- }
- }
-
- STACK_WIND (frame, qr_lookup_cbk, FIRST_CHILD(this),
- FIRST_CHILD(this)->fops->lookup, loc, xdata);
-
- if (new_req_dict) {
- dict_unref (new_req_dict);
- }
-
- return 0;
+ qr_private_t *priv = NULL;
+ qr_inode_table_t *table = NULL;
+ qr_inode_t *qr_inode = NULL;
-unwind:
- QR_STACK_UNWIND (lookup, frame, op_ret, op_errno, NULL, NULL,
- NULL, NULL);
+ qr_inode = qr_inode_ctx_get (this, inode);
+ if (!qr_inode)
+ return;
- if (new_req_dict) {
- dict_unref (new_req_dict);
- }
+ priv = this->private;
+ table = &priv->table;
- return 0;
+ LOCK (&table->lock);
+ {
+ __qr_inode_prune (table, qr_inode);
+ }
+ UNLOCK (&table->lock);
}
-int32_t
-qr_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
- int32_t op_errno, fd_t *fd, dict_t *xdata)
+/* To be called with priv->table.lock held */
+void
+__qr_cache_prune (qr_inode_table_t *table, qr_conf_t *conf)
{
- uint64_t value = 0;
- int32_t ret = -1;
- qr_local_t *local = NULL;
- qr_inode_t *qr_inode = NULL;
- qr_fd_ctx_t *qr_fd_ctx = NULL;
- call_stub_t *stub = NULL, *tmp = NULL;
- char is_open = 0;
- qr_private_t *priv = NULL;
- qr_inode_table_t *table = NULL;
- struct list_head waiting_ops;
-
- GF_ASSERT (frame);
-
- priv = this->private;
- table = &priv->table;
-
- local = frame->local;
- if (local != NULL) {
- is_open = local->is_open;
- }
-
- INIT_LIST_HEAD (&waiting_ops);
-
- ret = fd_ctx_get (fd, this, &value);
- if ((ret == -1) && (op_ret != -1)) {
- op_ret = -1;
- op_errno = EINVAL;
- gf_log (this->name, GF_LOG_WARNING,
- "cannot find quick-read context in fd (%p) opened on "
- "inode (gfid: %s)", fd, uuid_utoa (fd->inode->gfid));
- goto out;
- }
+ qr_inode_t *curr = NULL;
+ qr_inode_t *next = NULL;
+ int index = 0;
+ size_t size_pruned = 0;
- if (value) {
- qr_fd_ctx = (qr_fd_ctx_t *) (long)value;
- }
-
- if (qr_fd_ctx) {
- LOCK (&qr_fd_ctx->lock);
- {
- qr_fd_ctx->open_in_transit = 0;
-
- if (op_ret == 0) {
- qr_fd_ctx->opened = 1;
- }
- list_splice_init (&qr_fd_ctx->waiting_ops,
- &waiting_ops);
- }
- UNLOCK (&qr_fd_ctx->lock);
-
- if (local && local->is_open
- && ((local->open_flags & O_TRUNC) == O_TRUNC)) {
- LOCK (&table->lock);
- {
- ret = inode_ctx_del (fd->inode, this, &value);
- if (ret == 0) {
- qr_inode = (qr_inode_t *)(long) value;
-
- if (qr_inode != NULL) {
- __qr_inode_free (qr_inode);
- }
- }
- }
- UNLOCK (&table->lock);
- }
+ for (index = 0; index < conf->max_pri; index++) {
+ list_for_each_entry_safe (curr, next, &table->lru[index], lru) {
- if (!list_empty (&waiting_ops)) {
- list_for_each_entry_safe (stub, tmp, &waiting_ops,
- list) {
- list_del_init (&stub->list);
- if (op_ret < 0) {
- qr_local_t *local = NULL;
+ size_pruned += curr->size;
- local = stub->frame->local;
- local->op_ret = op_ret;
- local->op_errno = op_errno;
- }
+ __qr_inode_prune (table, curr);
- call_resume (stub);
- }
+ if (table->cache_used < conf->cache_size)
+ return;
}
}
-out:
- if (is_open) {
- QR_STACK_UNWIND (open, frame, op_ret, op_errno, fd, xdata);
- } else {
- STACK_DESTROY (frame->root);
- }
- return 0;
+ return;
}
-int32_t
-qr_open (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags,
- fd_t *fd, dict_t *xdata)
+void
+qr_cache_prune (xlator_t *this)
{
- qr_inode_t *qr_inode = NULL;
- int32_t ret = -1;
- uint64_t filep = 0;
- char content_cached = 0;
- qr_fd_ctx_t *qr_fd_ctx = NULL, *tmp_fd_ctx = NULL;
- int32_t op_ret = -1, op_errno = EINVAL;
- qr_local_t *local = NULL;
- qr_private_t *priv = NULL;
- qr_inode_table_t *table = NULL;
-
- GF_ASSERT (frame);
- GF_VALIDATE_OR_GOTO (frame->this->name, this, unwind);
- GF_VALIDATE_OR_GOTO (frame->this->name, this->private, unwind);
- GF_VALIDATE_OR_GOTO (frame->this->name, fd, unwind);
+ qr_private_t *priv = NULL;
+ qr_conf_t *conf = NULL;
+ qr_inode_table_t *table = NULL;
priv = this->private;
table = &priv->table;
+ conf = &priv->conf;
- tmp_fd_ctx = qr_fd_ctx = GF_CALLOC (1, sizeof (*qr_fd_ctx),
- gf_qr_mt_qr_fd_ctx_t);
- if (qr_fd_ctx == NULL) {
- op_ret = -1;
- op_errno = ENOMEM;
- goto unwind;
- }
-
- LOCK_INIT (&qr_fd_ctx->lock);
- INIT_LIST_HEAD (&qr_fd_ctx->waiting_ops);
- INIT_LIST_HEAD (&qr_fd_ctx->inode_list);
- qr_fd_ctx->fd = fd;
-
- qr_fd_ctx->path = gf_strdup (loc->path);
- if (qr_fd_ctx->path == NULL) {
- op_ret = -1;
- op_errno = ENOMEM;
- goto unwind;
- }
-
- qr_fd_ctx->flags = flags;
-
- ret = fd_ctx_set (fd, this, (uint64_t)(long)qr_fd_ctx);
- if (ret == -1) {
- op_ret = -1;
- op_errno = EINVAL;
- gf_log (this->name, GF_LOG_WARNING,
- "cannot set quick-read context in "
- "fd (%p) opened on inode (gfid:%s)", fd,
- uuid_utoa (fd->inode->gfid));
- goto unwind;
- }
-
- tmp_fd_ctx = NULL;
-
- local = qr_local_new (this);
- if (local == NULL) {
- op_ret = -1;
- op_errno = ENOMEM;
- goto unwind;
- }
-
- local->is_open = 1;
- local->open_flags = flags;
- frame->local = local;
- LOCK (&table->lock);
- {
- ret = inode_ctx_get (fd->inode, this, &filep);
- if (ret == 0) {
- qr_inode = (qr_inode_t *)(long) filep;
- if (qr_inode) {
- if (qr_inode->xattr) {
- content_cached = 1;
- }
- }
- }
- }
- UNLOCK (&table->lock);
-
- if (content_cached && (flags & O_DIRECTORY)) {
- op_ret = -1;
- op_errno = ENOTDIR;
- gf_log (this->name, GF_LOG_WARNING,
- "open with O_DIRECTORY flag received on non-directory");
- goto unwind;
- }
-
- if (!content_cached || ((flags & O_ACCMODE) == O_WRONLY)
- || ((flags & O_TRUNC) == O_TRUNC)
- || ((flags & O_DIRECT) == O_DIRECT)) {
- LOCK (&qr_fd_ctx->lock);
- {
- /*
- * we really need not set this flag, since open is
- * not yet unwound.
- */
-
- qr_fd_ctx->open_in_transit = 1;
- if ((flags & O_DIRECT) == O_DIRECT) {
- qr_fd_ctx->disabled = 1;
- }
- }
- UNLOCK (&qr_fd_ctx->lock);
- goto wind;
- } else {
- op_ret = 0;
- op_errno = 0;
-
- LOCK (&fd->inode->lock);
- {
- list_add_tail (&qr_fd_ctx->inode_list,
- &qr_inode->fd_list);
- }
- UNLOCK (&fd->inode->lock);
- }
-
-unwind:
- if (tmp_fd_ctx != NULL) {
- qr_fd_ctx_free (tmp_fd_ctx);
- }
-
- QR_STACK_UNWIND (open, frame, op_ret, op_errno, fd, NULL);
- return 0;
-
-wind:
- STACK_WIND (frame, qr_open_cbk, FIRST_CHILD(this),
- FIRST_CHILD(this)->fops->open, loc, flags, fd,
- xdata);
- return 0;
-}
-
-
-static inline time_t
-qr_time_elapsed (struct timeval *now, struct timeval *then)
-{
- time_t time_elapsed = 0;
-
- GF_VALIDATE_OR_GOTO ("quick-read", now, out);
- GF_VALIDATE_OR_GOTO ("quick-read", then, out);
-
- time_elapsed = now->tv_sec - then->tv_sec;
-
-out:
- return time_elapsed;
+ LOCK (&table->lock);
+ {
+ if (table->cache_used > conf->cache_size)
+ __qr_cache_prune (table, conf);
+ }
+ UNLOCK (&table->lock);
}
-static inline char
-qr_need_validation (qr_conf_t *conf, qr_inode_t *qr_inode)
+void *
+qr_content_extract (dict_t *xdata)
{
- struct timeval now = {0, };
- char need_validation = 0;
+ data_t *data = NULL;
+ void *content = NULL;
- GF_VALIDATE_OR_GOTO ("quick-read", conf, out);
- GF_VALIDATE_OR_GOTO ("quick-read", qr_inode, out);
+ data = dict_get (xdata, GF_CONTENT_KEY);
+ if (!data)
+ return NULL;
- gettimeofday (&now, NULL);
+ content = GF_CALLOC (1, data->len, gf_qr_mt_content_t);
+ if (!content)
+ return NULL;
- if (qr_time_elapsed (&now, &qr_inode->tv) >= conf->cache_timeout)
- need_validation = 1;
+ memcpy (content, data->data, data->len);
-out:
- return need_validation;
+ return content;
}
-static int32_t
-qr_validate_cache_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, struct iatt *buf,
- dict_t *xdata)
+void
+qr_content_update (xlator_t *this, qr_inode_t *qr_inode, void *data,
+ struct iatt *buf)
{
- qr_inode_t *qr_inode = NULL;
- qr_local_t *local = NULL;
- uint64_t value = 0;
- int32_t ret = 0;
- qr_private_t *priv = NULL;
- qr_inode_table_t *table = NULL;
- call_stub_t *stub = NULL;
-
- GF_ASSERT (frame);
- if (this == NULL) {
- op_ret = -1;
- op_errno = EINVAL;
- gf_log (frame->this->name, GF_LOG_WARNING,
- "xlator object (this) is NULL");
- goto unwind;
- }
-
- local = frame->local;
- if ((local == NULL) || ((local->fd) == NULL)) {
- op_ret = -1;
- op_errno = EINVAL;
- gf_log (frame->this->name, GF_LOG_WARNING,
- (local == NULL) ? "local is NULL"
- : "fd is not stored in local");
- goto unwind;
- }
-
- local->just_validated = 1;
-
- if (op_ret == -1) {
- goto unwind;
- }
+ qr_private_t *priv = NULL;
+ qr_inode_table_t *table = NULL;
priv = this->private;
table = &priv->table;
- LOCK (&table->lock);
- {
- ret = inode_ctx_get (local->fd->inode, this, &value);
- if (ret == 0) {
- qr_inode = (qr_inode_t *)(long) value;
- }
+ LOCK (&table->lock);
+ {
+ __qr_inode_prune (table, qr_inode);
- if (qr_inode != NULL) {
- gettimeofday (&qr_inode->tv, NULL);
+ qr_inode->data = data;
+ qr_inode->size = buf->ia_size;
- if ((qr_inode->stbuf.ia_mtime != buf->ia_mtime)
- || (qr_inode->stbuf.ia_mtime_nsec
- != buf->ia_mtime_nsec)) {
- inode_ctx_del (local->fd->inode, this, NULL);
- __qr_inode_free (qr_inode);
- }
- }
- }
- UNLOCK (&table->lock);
+ qr_inode->ia_mtime = buf->ia_mtime;
+ qr_inode->ia_mtime_nsec = buf->ia_mtime_nsec;
- stub = local->stub;
- local->stub = NULL;
+ qr_inode->buf = *buf;
- call_resume (stub);
+ gettimeofday (&qr_inode->last_refresh, NULL);
- return 0;
+ __qr_inode_register (table, qr_inode);
+ }
+ UNLOCK (&table->lock);
-unwind:
- /* this is actually unwind of readv */
- QR_STACK_UNWIND (readv, frame, op_ret, op_errno, NULL, -1, NULL, NULL,
- NULL);
- return 0;
+ qr_cache_prune (this);
}
-int32_t
-qr_validate_cache_helper (call_frame_t *frame, xlator_t *this, fd_t *fd,
- dict_t *xdata)
+gf_boolean_t
+qr_size_fits (qr_conf_t *conf, struct iatt *buf)
{
- qr_local_t *local = NULL;
- int32_t op_ret = -1, op_errno = -1;
-
- GF_ASSERT (frame);
- GF_VALIDATE_OR_GOTO (frame->this->name, this, out);
-
- local = frame->local;
- if (local == NULL) {
- op_ret = -1;
- op_errno = EINVAL;
- } else {
- op_ret = local->op_ret;
- op_errno = local->op_errno;
- }
-
-out:
- if (op_ret == -1) {
- qr_validate_cache_cbk (frame, NULL, this, op_ret, op_errno,
- NULL, NULL);
- } else {
- STACK_WIND (frame, qr_validate_cache_cbk, FIRST_CHILD (this),
- FIRST_CHILD (this)->fops->fstat, fd, xdata);
- }
-
- return 0;
+ return (buf->ia_size <= conf->max_file_size);
}
-int
-qr_validate_cache (call_frame_t *frame, xlator_t *this, fd_t *fd,
- call_stub_t *stub)
+gf_boolean_t
+qr_mtime_equal (qr_inode_t *qr_inode, struct iatt *buf)
{
- int ret = -1;
- int flags = 0;
- uint64_t value = 0;
- loc_t loc = {0, };
- char *path = NULL;
- qr_local_t *local = NULL;
- qr_fd_ctx_t *qr_fd_ctx = NULL;
- call_stub_t *validate_stub = NULL;
- char need_open = 0, can_wind = 0, validate_cbk_called = 0;
- call_frame_t *open_frame = NULL;
-
- GF_ASSERT (frame);
- GF_VALIDATE_OR_GOTO (frame->this->name, this, out);
- GF_VALIDATE_OR_GOTO (frame->this->name, fd, out);
- GF_VALIDATE_OR_GOTO (frame->this->name, stub, out);
-
- if (frame->local == NULL) {
- local = qr_local_new (this);
- if (local == NULL) {
- goto out;
- }
- } else {
- local = frame->local;
- }
-
- local->fd = fd;
- local->stub = stub;
- frame->local = local;
-
- ret = fd_ctx_get (fd, this, &value);
- if (ret == 0) {
- qr_fd_ctx = (qr_fd_ctx_t *)(long) value;
- }
-
- if (qr_fd_ctx) {
- LOCK (&qr_fd_ctx->lock);
- {
- path = qr_fd_ctx->path;
- flags = qr_fd_ctx->flags;
-
- if (!(qr_fd_ctx->opened
- || qr_fd_ctx->open_in_transit)) {
- need_open = 1;
- qr_fd_ctx->open_in_transit = 1;
- }
-
- if (qr_fd_ctx->opened) {
- can_wind = 1;
- } else {
- validate_stub = fop_fstat_stub (frame,
- qr_validate_cache_helper,
- fd, NULL);
- if (validate_stub == NULL) {
- ret = -1;
- if (need_open) {
- qr_fd_ctx->open_in_transit = 0;
- }
- goto unlock;
- }
-
- list_add_tail (&validate_stub->list,
-