summaryrefslogtreecommitdiffstats
path: root/xlators
diff options
context:
space:
mode:
authorRaghavendra G <raghavendra@gluster.com>2009-08-26 01:36:11 +0000
committerAnand V. Avati <avati@dev.gluster.com>2009-09-08 01:40:57 -0700
commitebc5d9888dfd7fcc000fac82dcfbad9fb91a9082 (patch)
tree3cc5837cd861560a582d6beaa9a8b870f25e4907 /xlators
parentbcd092a21f4284277a7f59c58715bb253ed90ff7 (diff)
performance/stat-prefetch: implement sp_lookup.
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.c283
-rw-r--r--xlators/performance/stat-prefetch/src/stat-prefetch.h31
2 files changed, 314 insertions, 0 deletions
diff --git a/xlators/performance/stat-prefetch/src/stat-prefetch.c b/xlators/performance/stat-prefetch/src/stat-prefetch.c
index 6a10ac4c42c..5823634fa73 100644
--- a/xlators/performance/stat-prefetch/src/stat-prefetch.c
+++ b/xlators/performance/stat-prefetch/src/stat-prefetch.c
@@ -18,6 +18,287 @@
*/
#include "stat-prefetch.h"
+#include "locking.h"
+
+
+void
+sp_local_free (sp_local_t *local)
+{
+ loc_wipe (&local->loc);
+ FREE (local);
+}
+
+
+int32_t
+sp_cache_remove_entry (sp_cache_t *cache, char *name, char remove_all)
+{
+ int32_t ret = -1;
+ gf_dirent_t *entry = NULL, *tmp = NULL;
+ char found = 0;
+
+ if ((cache == NULL) || ((name == NULL) && !remove_all)) {
+ goto out;
+ }
+
+ LOCK (&cache->lock);
+ {
+ list_for_each_entry_safe (entry, tmp, &cache->entries.list,
+ list) {
+ if (remove_all || (!strcmp (name, entry->d_name))) {
+ list_del_init (&entry->list);
+ found = 1;
+ ret = 0;
+
+ if (!remove_all) {
+ break;
+ }
+ }
+ }
+ }
+ UNLOCK (&cache->lock);
+
+ if (found) {
+ FREE (entry);
+ }
+out:
+ return ret;
+}
+
+
+int32_t
+sp_cache_get_entry (sp_cache_t *cache, char *name, gf_dirent_t *entry)
+{
+ int32_t ret = -1;
+ gf_dirent_t *tmp = NULL;
+
+ if ((cache == NULL) || (name == NULL) || (entry == NULL)) {
+ goto out;
+ }
+
+ LOCK (&cache->lock);
+ {
+ list_for_each_entry (tmp, &cache->entries.list, list) {
+ if (!strcmp (name, tmp->d_name)) {
+ memcpy (entry, tmp, sizeof (*entry));
+ ret = 0;
+ break;
+ }
+ }
+
+ }
+ UNLOCK (&cache->lock);
+
+out:
+ return ret;
+}
+
+
+void
+sp_cache_free (sp_cache_t *cache)
+{
+ sp_cache_remove_entry (cache, NULL, 1);
+ FREE (cache);
+}
+
+
+sp_cache_t *
+sp_get_cache_fd (xlator_t *this, fd_t *fd)
+{
+ sp_cache_t *cache = NULL;
+ uint64_t value = 0;
+ int32_t ret = -1;
+
+ if (fd == NULL) {
+ goto out;
+ }
+
+ ret = fd_ctx_get (fd, this, &value);
+ if (ret == -1) {
+ goto out;
+ }
+
+ cache = (void *)(long) value;
+out:
+ return cache;
+}
+
+sp_cache_t *
+sp_get_cache_inode (xlator_t *this, inode_t *inode, int32_t pid)
+{
+ fd_t *fd = NULL;
+ sp_cache_t *cache = NULL;
+
+ if (inode == NULL) {
+ goto out;
+ }
+
+ fd = fd_lookup (inode, pid);
+ if (fd == NULL) {
+ goto out;
+ }
+
+ cache = sp_get_cache_fd (this, fd);
+out:
+ return cache;
+}
+
+
+int32_t
+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 *stbuf = NULL;
+ int32_t ret = -1;
+
+ if (op_ret == -1) {
+ goto out;
+ }
+
+ if (S_ISDIR (buf->st_mode)) {
+ 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 out;
+ }
+
+ memcpy (stbuf, buf, sizeof (*stbuf));
+ 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 out;
+ }
+ }
+
+out:
+ SP_STACK_UNWIND (frame, op_ret, op_errno, inode, buf, dict);
+ return 0;
+}
+
+
+int32_t
+sp_lookup_behind_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)
+{
+ sp_local_t *local = NULL;
+ sp_cache_t *cache = NULL;
+
+ local = frame->local;
+ if (local == NULL) {
+ goto out;
+ }
+
+ if ((op_ret == -1) && (op_errno = ENOENT)) {
+ cache = sp_get_cache_inode (this, local->loc.parent,
+ frame->root->pid);
+
+ if (cache) {
+ sp_cache_remove_entry (cache, (char *)local->loc.name,
+ 0);
+ }
+ }
+
+out:
+ SP_STACK_DESTROY (frame);
+ return 0;
+}
+
+
+int32_t
+sp_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req)
+{
+ sp_local_t *local = NULL;
+ gf_dirent_t dirent;
+ int32_t ret = -1, op_ret = -1, op_errno = EINVAL;
+ sp_cache_t *cache = NULL;
+ struct stat *postparent = NULL, *buf = NULL;
+ uint64_t value = 0;
+ call_frame_t *wind_frame = NULL;
+ char lookup_behind = 0;
+
+ if ((loc == NULL) || (loc->parent == NULL) || (loc->name == NULL)) {
+ goto unwind;
+ }
+
+ if (xattr_req) {
+ goto wind;
+ }
+
+ memset (&dirent, 0, sizeof (dirent));
+ cache = sp_get_cache_inode (this, loc->parent, frame->root->pid);
+ if (cache) {
+ 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;
+ op_ret = 0;
+ op_errno = 0;
+ lookup_behind = 1;
+ }
+ }
+ }
+
+wind:
+ if (lookup_behind) {
+ wind_frame = copy_frame (frame);
+ if (wind_frame == NULL) {
+ op_ret = -1;
+ op_errno = ENOMEM;
+ gf_log (this->name, GF_LOG_ERROR, "out of memory");
+ goto unwind;
+ }
+
+ local = CALLOC (1, sizeof (*local));
+ if (local == NULL) {
+ op_ret = -1;
+ op_errno = ENOMEM;
+ STACK_DESTROY (wind_frame->root);
+ goto unwind;
+ }
+
+ loc_copy (&local->loc, loc);
+ wind_frame->local = local;
+ STACK_WIND (wind_frame, sp_lookup_behind_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->lookup, loc, xattr_req);
+ } else {
+ STACK_WIND (frame, sp_lookup_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->lookup, loc, xattr_req);
+
+ return 0;
+ }
+
+unwind:
+ SP_STACK_UNWIND (frame, op_ret, op_errno, loc->inode, buf, postparent,
+ NULL);
+ return 0;
+
+}
+
+int32_t
+sp_forget (xlator_t *this, inode_t *inode)
+{
+ struct stat *buf = NULL;
+ uint64_t value = 0;
+
+ inode_ctx_del (inode, this, &value);
+
+ if (value) {
+ buf = (void *)(long)value;
+ FREE (buf);
+ }
+
+ return 0;
+}
+
int32_t
init (xlator_t *this)
@@ -44,10 +325,12 @@ fini (xlator_t *this)
struct xlator_fops fops = {
+ .lookup = sp_lookup,
};
struct xlator_mops mops = {
};
struct xlator_cbks cbks = {
+ .forget = sp_forget,
};
diff --git a/xlators/performance/stat-prefetch/src/stat-prefetch.h b/xlators/performance/stat-prefetch/src/stat-prefetch.h
index bd8d9e7eb17..cf6bdd89dd6 100644
--- a/xlators/performance/stat-prefetch/src/stat-prefetch.h
+++ b/xlators/performance/stat-prefetch/src/stat-prefetch.h
@@ -29,4 +29,35 @@
#include "dict.h"
#include "xlator.h"
+struct sp_cache {
+ gf_dirent_t entries; /* Head of list of cached dirents. */
+ uint64_t expected_offset; /* Offset where the next read will
+ * happen.
+ */
+ gf_lock_t lock;
+};
+typedef struct sp_cache sp_cache_t;
+
+struct sp_local {
+ loc_t loc;
+};
+typedef struct sp_local sp_local_t;
+
+
+void sp_local_free (sp_local_t *local);
+
+#define SP_STACK_UNWIND(frame, params ...) do { \
+ sp_local_t *__local = frame->local; \
+ frame->local = NULL; \
+ STACK_UNWIND (frame, params); \
+ sp_local_free (__local); \
+} while (0)
+
+#define SP_STACK_DESTROY(frame) do { \
+ sp_local_t *__local = frame->local; \
+ frame->local = NULL; \
+ STACK_DESTROY (frame->root); \
+ sp_local_free (__local); \
+} while (0)
+
#endif /* #ifndef _STAT_PREFETCH_H */