summaryrefslogtreecommitdiffstats
path: root/xlators
diff options
context:
space:
mode:
authorRaghavendra G <raghavendra@gluster.com>2009-10-08 06:21:07 +0000
committerAnand V. Avati <avati@dev.gluster.com>2009-10-09 00:48:34 -0700
commit2dc9d11fe1c8aaeba972c6fd693de1f32e5e3f1a (patch)
tree81e74c8073f490376e314dfcbd7063053684c439 /xlators
parent490edcd9f76726e5cc46bf9e7ddd69e496d32d7b (diff)
performance/stat-prefetch: Add support code to implement lookup-behind.
- change sp_lookup and sp_lookup_cbk to support sending lookups when needed. lookups might need to be sent in fops like open, chmod, chown etc which operate on a path, since the actual lookup sent to stat-prefetch by its parent xlators is not propagated down the xlator tree if the path is cached. Signed-off-by: Anand V. Avati <avati@dev.gluster.com> BUG: 221 (stat prefetch implementation) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=221
Diffstat (limited to 'xlators')
-rw-r--r--xlators/performance/stat-prefetch/src/stat-prefetch.c239
-rw-r--r--xlators/performance/stat-prefetch/src/stat-prefetch.h15
2 files changed, 199 insertions, 55 deletions
diff --git a/xlators/performance/stat-prefetch/src/stat-prefetch.c b/xlators/performance/stat-prefetch/src/stat-prefetch.c
index 883345a2d3b..b96e92c6e2c 100644
--- a/xlators/performance/stat-prefetch/src/stat-prefetch.c
+++ b/xlators/performance/stat-prefetch/src/stat-prefetch.c
@@ -18,9 +18,6 @@
*/
#include "stat-prefetch.h"
-#include "locking.h"
-#include "inode.h"
-#include <libgen.h>
#define GF_SP_CACHE_BUCKETS 4096
@@ -374,53 +371,123 @@ sp_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, inode_t *inode,
struct stat *buf, dict_t *dict, struct stat *postparent)
{
- struct stat *stbuf = NULL;
- int32_t ret = -1;
- uint64_t value = 0;
+ sp_inode_ctx_t *inode_ctx = NULL;
+ uint64_t value = 0;
+ int ret = 0;
+ struct list_head waiting_ops = {0, };
+ call_stub_t *stub = NULL, *tmp = NULL;
+ sp_local_t *local = NULL;
+ sp_cache_t *cache = NULL;
- if (op_ret == -1) {
- goto out;
+ INIT_LIST_HEAD (&waiting_ops);
+
+ local = frame->local;
+ if (local == NULL) {
+ op_ret = -1;
+ op_errno = EINVAL;
+ } else if (op_ret == -1) {
+ cache = sp_get_cache_inode (this, local->loc.parent,
+ frame->root->pid);
+
+ if (cache) {
+ sp_cache_remove_entry (cache, (char *)local->loc.name,
+ 0);
+ }
}
- if (S_ISDIR (buf->st_mode)) {
- LOCK (&inode->lock);
+ ret = inode_ctx_get (inode, this, &value);
+ if (ret == 0) {
+ inode_ctx = (sp_inode_ctx_t *)(long)value;
+ if (inode_ctx == NULL) {
+ op_ret = -1;
+ op_errno = EINVAL;
+ goto out;
+ }
+
+ LOCK (&inode_ctx->lock);
{
- ret = __inode_ctx_get (inode, this, &value);
- if (ret == 0) {
- stbuf = (struct stat *)(long)value;
+ inode_ctx->op_ret = op_ret;
+ inode_ctx->op_errno = op_errno;
+ inode_ctx->looked_up = 1;
+ inode_ctx->lookup_in_progress = 0;
+ if (S_ISDIR (buf->st_mode) && (op_ret == 0)) {
+ memcpy (&inode_ctx->stbuf, buf,
+ sizeof (*buf));
}
+ list_splice_init (&inode_ctx->waiting_ops,
+ &waiting_ops);
+ }
+ UNLOCK (&inode_ctx->lock);
- if (stbuf == NULL) {
- stbuf = CALLOC (1, sizeof (*stbuf));
- if (stbuf == NULL) {
- op_ret = -1;
- op_errno = ENOMEM;
- gf_log (this->name, GF_LOG_ERROR,
- "out of memory");
- goto unlock;
- }
+ list_for_each_entry_safe (stub, tmp, &waiting_ops, list) {
+ list_del_init (&stub->list);
+ call_resume (stub);
+ }
+ } else {
+ op_errno = EINVAL;
+ op_ret = -1;
+ }
- ret = __inode_ctx_put (inode, this,
- (long)stbuf);
- if (ret == -1) {
- op_ret = -1;
-
- /* FIXME: EINVAL is not correct */
- op_errno = EINVAL;
- FREE (stbuf);
- goto unlock;
- }
+out:
+ if ((local != NULL) && (local->is_lookup)) {
+ SP_STACK_UNWIND (frame, op_ret, op_errno, inode, buf, dict);
+ }
+
+ return 0;
+}
+
+void
+sp_inode_ctx_free (xlator_t *this, sp_inode_ctx_t *ctx)
+{
+ call_stub_t *stub = NULL, *tmp = NULL;
+
+ if (ctx == NULL) {
+ goto out;
+ }
+
+ LOCK (&ctx->lock);
+ {
+ if (!list_empty (&ctx->waiting_ops)) {
+ gf_log (this->name, GF_LOG_CRITICAL, "inode ctx is "
+ "being freed even when there are file "
+ "operations waiting for lookup-behind to "
+ "complete. The operations in the waiting list "
+ "are:");
+ list_for_each_entry_safe (stub, tmp, &ctx->waiting_ops,
+ list) {
+ gf_log (this->name, GF_LOG_CRITICAL,
+ "OP (%d)", stub->fop);
+
+ list_del_init (&stub->list);
+ call_stub_destroy (stub);
}
-
- memcpy (stbuf, buf, sizeof (*stbuf));
}
- unlock:
- UNLOCK (&inode->lock);
}
+ UNLOCK (&ctx->lock);
+
+ LOCK_DESTROY (&ctx->lock);
+ FREE (ctx);
out:
- SP_STACK_UNWIND (frame, op_ret, op_errno, inode, buf, dict);
- return 0;
+ return;
+}
+
+
+sp_inode_ctx_t *
+sp_inode_ctx_init ()
+{
+ sp_inode_ctx_t *inode_ctx = NULL;
+
+ inode_ctx = CALLOC (1, sizeof (*inode_ctx));
+ if (inode_ctx == NULL) {
+ goto out;
+ }
+
+ LOCK_INIT (&inode_ctx->lock);
+ INIT_LIST_HEAD (&inode_ctx->waiting_ops);
+
+out:
+ return inode_ctx;
}
@@ -520,19 +587,48 @@ sp_is_empty (dict_t *this, char *key, data_t *value, void *data)
}
}
-
+/*
+ * TODO: implement sending lookups for every fop done on this path. As of now
+ * lookup on the path is sent only for the first fop on this path.
+ */
int32_t
sp_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req)
{
- gf_dirent_t dirent;
- char entry_cached = 0;
- uint64_t value = 0;
- char xattr_req_empty = 1;
- sp_cache_t *cache = NULL;
- struct stat *postparent = NULL, *buf = NULL;
- int32_t ret = -1, op_ret = -1, op_errno = EINVAL;
+ gf_dirent_t dirent;
+ char entry_cached = 0;
+ uint64_t value = 0;
+ char xattr_req_empty = 1;
+ sp_cache_t *cache = NULL;
+ struct stat postparent = {0, }, buf = {0, };
+ int32_t ret = -1, op_ret = -1, op_errno = EINVAL;
+ sp_inode_ctx_t *inode_ctx = NULL;
+ sp_local_t *local = NULL;
+
+ if (loc == NULL || loc->inode == NULL) {
+ goto unwind;
+ }
+
+ LOCK (&loc->inode->lock);
+ {
+ ret = __inode_ctx_get (loc->inode, this, &value);
+ if (ret == 0) {
+ inode_ctx = (sp_inode_ctx_t *)(long)value;
+ } else {
+ inode_ctx = sp_inode_ctx_init ();
+ if (inode_ctx != NULL) {
+ ret = __inode_ctx_put (loc->inode, this,
+ (long)inode_ctx);
+ if (ret == -1) {
+ sp_inode_ctx_free (this, inode_ctx);
+ inode_ctx = NULL;
+ }
+ }
+ }
+ }
+ UNLOCK (&loc->inode->lock);
- if (loc == NULL) {
+ if (inode_ctx == NULL) {
+ op_errno = ENOMEM;
goto unwind;
}
@@ -554,9 +650,10 @@ sp_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req)
ret = sp_cache_get_entry (cache, (char *)loc->name, &dirent);
if (ret == 0) {
ret = inode_ctx_get (loc->parent, this, &value);
- if (ret == 0) {
- postparent = (void *)(long)value;
- buf = &dirent.d_stat;
+ if ((ret == 0) && (value != 0)) {
+ inode_ctx = (void *)(long)value;
+ postparent = inode_ctx->stbuf;
+ buf = dirent.d_stat;
op_ret = 0;
op_errno = 0;
entry_cached = 1;
@@ -567,10 +664,15 @@ sp_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req)
if (cache) {
ret = sp_cache_get_entry (cache, ".", &dirent);
if (ret == 0) {
- buf = &dirent.d_stat;
- op_ret = 0;
- op_errno = 0;
- entry_cached = 1;
+ ret = inode_ctx_get (loc->parent, this, &value);
+ if ((ret == 0) && (value != 0)) {
+ inode_ctx = (void *)(long)value;
+ postparent = inode_ctx->stbuf;
+ buf = dirent.d_stat;
+ op_ret = 0;
+ op_errno = 0;
+ entry_cached = 1;
+ }
}
}
}
@@ -585,6 +687,33 @@ wind:
cache->miss++;
}
+ LOCK (&inode_ctx->lock);
+ {
+ if (!(inode_ctx->looked_up
+ || inode_ctx->lookup_in_progress)) {
+ inode_ctx->lookup_in_progress = 1;
+ }
+ }
+ UNLOCK (&inode_ctx->lock);
+
+ op_errno = ENOMEM;
+ local = CALLOC (1, sizeof (*local));
+ GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, local, unwind,
+ ENOMEM);
+ op_errno = 0;
+
+ frame->local = local;
+
+ ret = loc_copy (&local->loc, loc);
+ if (ret == -1) {
+ op_errno = errno;
+ gf_log (this->name, GF_LOG_ERROR, "%s",
+ strerror (op_errno));
+ goto unwind;
+ }
+
+ local->is_lookup = 1;
+
STACK_WIND (frame, sp_lookup_cbk, FIRST_CHILD(this),
FIRST_CHILD(this)->fops->lookup, loc, xattr_req);
@@ -592,7 +721,7 @@ wind:
}
unwind:
- SP_STACK_UNWIND (frame, op_ret, op_errno, loc->inode, buf, postparent,
+ SP_STACK_UNWIND (frame, op_ret, op_errno, loc->inode, &buf, &postparent,
NULL);
return 0;
diff --git a/xlators/performance/stat-prefetch/src/stat-prefetch.h b/xlators/performance/stat-prefetch/src/stat-prefetch.h
index dd6b067c5bd..81f504a7f31 100644
--- a/xlators/performance/stat-prefetch/src/stat-prefetch.h
+++ b/xlators/performance/stat-prefetch/src/stat-prefetch.h
@@ -25,11 +25,15 @@
#include "config.h"
#endif
+#include "locking.h"
+#include "inode.h"
#include "glusterfs.h"
#include "dict.h"
#include "xlator.h"
#include "rbthash.h"
#include "hashfn.h"
+#include "call-stub.h"
+#include <libgen.h>
struct sp_cache {
rbthash_table_t *table;
@@ -58,9 +62,20 @@ typedef struct sp_fd_ctx sp_fd_ctx_t;
struct sp_local {
loc_t loc;
fd_t *fd;
+ char is_lookup;
};
typedef struct sp_local sp_local_t;
+struct sp_inode_ctx {
+ char looked_up;
+ char lookup_in_progress;
+ int32_t op_ret;
+ int32_t op_errno;
+ struct stat stbuf;
+ gf_lock_t lock;
+ struct list_head waiting_ops;
+};
+typedef struct sp_inode_ctx sp_inode_ctx_t;
void sp_local_free (sp_local_t *local);