d1681e
From 30993baa95ef0eac8abd461f12839247b76d6e4c Mon Sep 17 00:00:00 2001
d1681e
From: Raghavendra G <rgowdapp@redhat.com>
d1681e
Date: Mon, 23 Apr 2018 19:21:20 +0530
d1681e
Subject: [PATCH 248/260] performance/md-cache: purge cache on ENOENT/ESTALE
d1681e
 errors
d1681e
d1681e
If not, next lookup could be served from cache and can be success,
d1681e
which is wrong. This can affect retry logic of VFS when it receives an
d1681e
ESTALE.
d1681e
d1681e
> Change-Id: Iad8e564d666aa4172823343f19a60c11e4416ef6
d1681e
> Signed-off-by: Raghavendra G <rgowdapp@redhat.com>
d1681e
> Fixes: bz#1571593
d1681e
d1681e
(cherry picked from commit 6912441543192a366f264b61d97d50faf3815a28)
d1681e
Change-Id: Iad8e564d666aa4172823343f19a60c11e4416ef6
d1681e
BUG: 1546717
d1681e
Signed-off-by: Raghavendra G <rgowdapp@redhat.com>
d1681e
Fixes: bz#1546717
d1681e
upstream: https://review.gluster.org/19926
d1681e
Reviewed-on: https://code.engineering.redhat.com/gerrit/136806
d1681e
Tested-by: RHGS Build Bot <nigelb@redhat.com>
d1681e
Reviewed-by: Poornima Gurusiddaiah <pgurusid@redhat.com>
d1681e
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
d1681e
---
d1681e
 xlators/performance/md-cache/src/md-cache.c | 624 ++++++++++++++++++++++++----
d1681e
 1 file changed, 545 insertions(+), 79 deletions(-)
d1681e
d1681e
diff --git a/xlators/performance/md-cache/src/md-cache.c b/xlators/performance/md-cache/src/md-cache.c
d1681e
index feab357..9d2eea6 100644
d1681e
--- a/xlators/performance/md-cache/src/md-cache.c
d1681e
+++ b/xlators/performance/md-cache/src/md-cache.c
d1681e
@@ -24,11 +24,18 @@
d1681e
 #include "md-cache-messages.h"
d1681e
 #include "statedump.h"
d1681e
 #include "atomic.h"
d1681e
+#include "timespec.h"
d1681e
 
d1681e
 /* TODO:
d1681e
    - cache symlink() link names and nuke symlink-cache
d1681e
    - send proper postbuf in setattr_cbk even when op_ret = -1
d1681e
 */
d1681e
+struct mdc_statfs_cache {
d1681e
+        pthread_mutex_t lock;
d1681e
+        gf_boolean_t initialized;
d1681e
+        struct timespec last_refreshed;
d1681e
+        struct statvfs buf;
d1681e
+};
d1681e
 
d1681e
 struct mdc_statistics {
d1681e
         gf_atomic_t stat_hit; /* No. of times lookup/stat was served from
d1681e
@@ -65,6 +72,8 @@ struct mdc_conf {
d1681e
         time_t last_child_down;
d1681e
         gf_lock_t lock;
d1681e
         struct mdc_statistics mdc_counter;
d1681e
+        gf_boolean_t cache_statfs;
d1681e
+        struct mdc_statfs_cache statfs_cache;
d1681e
 };
d1681e
 
d1681e
 
d1681e
@@ -1062,20 +1071,165 @@ mdc_xattr_satisfied (xlator_t *this, dict_t *req, dict_t *rsp)
d1681e
         return pair.ret;
d1681e
 }
d1681e
 
d1681e
+static void
d1681e
+mdc_cache_statfs (xlator_t *this, struct statvfs *buf)
d1681e
+{
d1681e
+        struct mdc_conf *conf = this->private;
d1681e
+
d1681e
+        pthread_mutex_lock (&conf->statfs_cache.lock);
d1681e
+        {
d1681e
+                memcpy (&conf->statfs_cache.buf, buf, sizeof (struct statvfs));
d1681e
+                clock_gettime (CLOCK_MONOTONIC,
d1681e
+                               &conf->statfs_cache.last_refreshed);
d1681e
+                conf->statfs_cache.initialized = _gf_true;
d1681e
+        }
d1681e
+        pthread_mutex_unlock (&conf->statfs_cache.lock);
d1681e
+}
d1681e
 
d1681e
 int
d1681e
-mdc_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
-                int32_t op_ret,	int32_t op_errno, inode_t *inode,
d1681e
-                struct iatt *stbuf, dict_t *dict, struct iatt *postparent)
d1681e
+mdc_load_statfs_info_from_cache (xlator_t *this, struct statvfs **buf)
d1681e
 {
d1681e
-        mdc_local_t *local = NULL;
d1681e
         struct mdc_conf *conf = this->private;
d1681e
+        struct timespec now;
d1681e
+        double cache_age = 0.0;
d1681e
+        int ret = 0;
d1681e
+
d1681e
+        if (!buf || !conf) {
d1681e
+                ret = -1;
d1681e
+                goto err;
d1681e
+        }
d1681e
+
d1681e
+        pthread_mutex_lock (&conf->statfs_cache.lock);
d1681e
+        {
d1681e
+                *buf = NULL;
d1681e
+
d1681e
+                /* Skip if the cache is not initialized */
d1681e
+                if (!conf->statfs_cache.initialized) {
d1681e
+                        ret = -1;
d1681e
+                        goto err;
d1681e
+                }
d1681e
+
d1681e
+                timespec_now (&now;;
d1681e
+
d1681e
+                cache_age = (
d1681e
+                  now.tv_sec - conf->statfs_cache.last_refreshed.tv_sec);
d1681e
+
d1681e
+                gf_log (this->name, GF_LOG_DEBUG,
d1681e
+                        "STATFS cache age = %lf", cache_age);
d1681e
+                if (cache_age > conf->timeout) {
d1681e
+                        /* Expire the cache */
d1681e
+                        gf_log (this->name, GF_LOG_DEBUG,
d1681e
+                                "Cache age %lf exceeded timeout %d",
d1681e
+                                cache_age, conf->timeout);
d1681e
+                        ret = -1;
d1681e
+                        goto err;
d1681e
+                }
d1681e
+
d1681e
+                *buf = &conf->statfs_cache.buf;
d1681e
+        }
d1681e
+err:
d1681e
+        pthread_mutex_unlock (&conf->statfs_cache.lock);
d1681e
+        return ret;
d1681e
+}
d1681e
+
d1681e
+int
d1681e
+mdc_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
+                int32_t op_ret, int32_t op_errno,
d1681e
+                struct statvfs *buf, dict_t *xdata)
d1681e
+{
d1681e
+        struct mdc_conf *conf  = this->private;
d1681e
+        mdc_local_t     *local = NULL;
d1681e
+
d1681e
+        local = frame->local;
d1681e
+        if (!local)
d1681e
+                goto out;
d1681e
+
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ENOENT) || (op_errno == ESTALE)) {
d1681e
+                        mdc_inode_iatt_invalidate (this, local->loc.inode);
d1681e
+                }
d1681e
+
d1681e
+                goto out;
d1681e
+        }
d1681e
+
d1681e
+        if (conf && conf->cache_statfs) {
d1681e
+                mdc_cache_statfs (this, buf);
d1681e
+        }
d1681e
+
d1681e
+out:
d1681e
+        MDC_STACK_UNWIND (statfs, frame, op_ret, op_errno, buf, xdata);
d1681e
+
d1681e
+        return 0;
d1681e
+}
d1681e
+
d1681e
+int
d1681e
+mdc_statfs (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata)
d1681e
+{
d1681e
+        int              ret   = 0, op_ret = 0, op_errno = 0;
d1681e
+        struct statvfs  *buf   = NULL;
d1681e
+        mdc_local_t     *local = NULL;
d1681e
+        struct mdc_conf *conf  = this->private;
d1681e
+
d1681e
+        local = mdc_local_get (frame);
d1681e
+        if (!local) {
d1681e
+                op_ret = -1;
d1681e
+                op_errno = ENOMEM;
d1681e
+                goto out;
d1681e
+        }
d1681e
+
d1681e
+        loc_copy (&local->loc, loc);
d1681e
+
d1681e
+        if (!conf) {
d1681e
+                goto uncached;
d1681e
+        }
d1681e
+
d1681e
+        if (!conf->cache_statfs) {
d1681e
+                goto uncached;
d1681e
+        }
d1681e
+
d1681e
+        ret = mdc_load_statfs_info_from_cache (this, &buf;;
d1681e
+        if (ret == 0 && buf) {
d1681e
+                op_ret = 0;
d1681e
+                op_errno = 0;
d1681e
+                goto out;
d1681e
+        }
d1681e
+
d1681e
+uncached:
d1681e
+        STACK_WIND (frame, mdc_statfs_cbk, FIRST_CHILD (this),
d1681e
+                    FIRST_CHILD (this)->fops->statfs, loc, xdata);
d1681e
+        return 0;
d1681e
+
d1681e
+out:
d1681e
+        STACK_UNWIND_STRICT (statfs, frame, op_ret, op_errno, buf, xdata);
d1681e
+        return 0;
d1681e
+}
d1681e
+
d1681e
+int
d1681e
+mdc_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
+                int32_t       op_ret,	int32_t op_errno, inode_t *inode,
d1681e
+                struct iatt  *stbuf, dict_t *dict, struct iatt *postparent)
d1681e
+{
d1681e
+        mdc_local_t     *local = NULL;
d1681e
+        struct mdc_conf *conf  = this->private;
d1681e
 
d1681e
         local = frame->local;
d1681e
 
d1681e
         if (op_ret != 0) {
d1681e
                 if (op_errno == ENOENT)
d1681e
                         GF_ATOMIC_INC (conf->mdc_counter.negative_lookup);
d1681e
+
d1681e
+                if (op_errno == ESTALE) {
d1681e
+                        /* if op_errno is ENOENT, fuse-bridge will unlink the
d1681e
+                         * dentry
d1681e
+                         */
d1681e
+                        if (local->loc.parent)
d1681e
+                                mdc_inode_iatt_invalidate (this,
d1681e
+                                                           local->loc.parent);
d1681e
+                        else
d1681e
+                                mdc_inode_iatt_invalidate (this,
d1681e
+                                                           local->loc.inode);
d1681e
+                }
d1681e
+
d1681e
                 goto out;
d1681e
         }
d1681e
 
d1681e
@@ -1185,13 +1339,18 @@ mdc_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
 {
d1681e
         mdc_local_t  *local = NULL;
d1681e
 
d1681e
-        if (op_ret != 0)
d1681e
-                goto out;
d1681e
-
d1681e
         local = frame->local;
d1681e
         if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ESTALE) || (op_errno == ENOENT)) {
d1681e
+                        mdc_inode_iatt_invalidate (this, local->loc.inode);
d1681e
+                }
d1681e
+
d1681e
+                goto out;
d1681e
+        }
d1681e
+
d1681e
         mdc_inode_iatt_set (this, local->loc.inode, buf);
d1681e
 
d1681e
 out:
d1681e
@@ -1240,13 +1399,18 @@ mdc_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
 {
d1681e
         mdc_local_t  *local = NULL;
d1681e
 
d1681e
-        if (op_ret != 0)
d1681e
-                goto out;
d1681e
-
d1681e
         local = frame->local;
d1681e
         if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ENOENT) || (op_errno == ESTALE)) {
d1681e
+                        mdc_inode_iatt_invalidate (this, local->fd->inode);
d1681e
+                }
d1681e
+
d1681e
+                goto out;
d1681e
+        }
d1681e
+
d1681e
         mdc_inode_iatt_set (this, local->fd->inode, buf);
d1681e
 
d1681e
 out:
d1681e
@@ -1297,11 +1461,15 @@ mdc_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
 
d1681e
         local = frame->local;
d1681e
 
d1681e
-        if (op_ret != 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ESTALE) || (op_errno == ENOENT))
d1681e
+                        mdc_inode_iatt_invalidate (this, local->loc.inode);
d1681e
+
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         mdc_inode_iatt_set_validate(this, local->loc.inode, prebuf, postbuf,
d1681e
                                     _gf_true);
d1681e
@@ -1340,11 +1508,15 @@ mdc_ftruncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
 
d1681e
         local = frame->local;
d1681e
 
d1681e
-        if (op_ret != 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ENOENT) || (op_errno == ESTALE))
d1681e
+                        mdc_inode_iatt_invalidate (this, local->fd->inode);
d1681e
+
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         mdc_inode_iatt_set_validate(this, local->fd->inode, prebuf, postbuf,
d1681e
                                     _gf_true);
d1681e
@@ -1384,11 +1556,16 @@ mdc_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
 
d1681e
         local = frame->local;
d1681e
 
d1681e
-        if (op_ret != 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ESTALE) || (op_errno == ENOENT)) {
d1681e
+                        mdc_inode_iatt_invalidate (this, local->loc.parent);
d1681e
+                }
d1681e
+
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         if (local->loc.parent) {
d1681e
                 mdc_inode_iatt_set (this, local->loc.parent, postparent);
d1681e
@@ -1433,11 +1610,16 @@ mdc_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
 
d1681e
         local = frame->local;
d1681e
 
d1681e
-        if (op_ret != 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ESTALE) || (op_errno == ENOENT)) {
d1681e
+                        mdc_inode_iatt_invalidate (this, local->loc.parent);
d1681e
+                }
d1681e
+
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         if (local->loc.parent) {
d1681e
                 mdc_inode_iatt_set (this, local->loc.parent, postparent);
d1681e
@@ -1481,11 +1663,24 @@ mdc_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
 
d1681e
         local = frame->local;
d1681e
 
d1681e
-        if (op_ret != 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret != 0) {
d1681e
+                /* if errno is ESTALE, parent is not present, which implies even
d1681e
+                 * child is not present. Also, man 2 unlink states unlink can
d1681e
+                 * return ENOENT if a component in pathname does not
d1681e
+                 * exist or is a dangling symbolic link. So, invalidate both
d1681e
+                 * parent and child for both errno
d1681e
+                 */
d1681e
+
d1681e
+                if ((op_errno == ENOENT) || (op_errno == ESTALE)) {
d1681e
+                        mdc_inode_iatt_invalidate (this, local->loc.inode);
d1681e
+                        mdc_inode_iatt_invalidate (this, local->loc.parent);
d1681e
+                }
d1681e
+
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         if (local->loc.parent) {
d1681e
                 mdc_inode_iatt_set (this, local->loc.parent, postparent);
d1681e
@@ -1528,11 +1723,24 @@ mdc_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
 
d1681e
         local = frame->local;
d1681e
 
d1681e
-        if (op_ret != 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret != 0) {
d1681e
+                /* if errno is ESTALE, parent is not present, which implies even
d1681e
+                 * child is not present. Also, man 2 rmdir states rmdir can
d1681e
+                 * return ENOENT if a directory component in pathname does not
d1681e
+                 * exist or is a dangling symbolic link. So, invalidate both
d1681e
+                 * parent and child for both errno
d1681e
+                 */
d1681e
+
d1681e
+                if ((op_errno == ESTALE) || (op_errno == ENOENT)) {
d1681e
+                        mdc_inode_iatt_invalidate (this, local->loc.inode);
d1681e
+                        mdc_inode_iatt_invalidate (this, local->loc.parent);
d1681e
+                }
d1681e
+
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         if (local->loc.parent) {
d1681e
                 mdc_inode_iatt_set (this, local->loc.parent, postparent);
d1681e
@@ -1572,11 +1780,16 @@ mdc_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
 
d1681e
         local = frame->local;
d1681e
 
d1681e
-        if (op_ret != 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ESTALE) || (op_errno == ENOENT)) {
d1681e
+                        mdc_inode_iatt_invalidate (this, local->loc.parent);
d1681e
+                }
d1681e
+
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         if (local->loc.parent) {
d1681e
                 mdc_inode_iatt_set (this, local->loc.parent, postparent);
d1681e
@@ -1621,12 +1834,17 @@ mdc_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
         mdc_local_t *local = NULL;
d1681e
 
d1681e
         local = frame->local;
d1681e
-
d1681e
-        if (op_ret != 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ESTALE) || (op_errno == ENOENT)) {
d1681e
+                        mdc_inode_iatt_invalidate (this, local->loc.inode);
d1681e
+                        mdc_inode_iatt_invalidate (this, local->loc2.parent);
d1681e
+                }
d1681e
+
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         if (local->loc.parent) {
d1681e
                 mdc_inode_iatt_set (this, local->loc.parent, postoldparent);
d1681e
@@ -1678,11 +1896,17 @@ mdc_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
 
d1681e
         local = frame->local;
d1681e
 
d1681e
-        if (op_ret != 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ENOENT) || (op_errno == ESTALE)) {
d1681e
+                        mdc_inode_iatt_invalidate (this, local->loc.inode);
d1681e
+                        mdc_inode_iatt_invalidate (this, local->loc2.parent);
d1681e
+                }
d1681e
+
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         if (local->loc.inode) {
d1681e
                 mdc_inode_iatt_set (this, local->loc.inode, buf);
d1681e
@@ -1726,11 +1950,16 @@ mdc_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
 
d1681e
         local = frame->local;
d1681e
 
d1681e
-        if (op_ret != 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ESTALE) || (op_errno == ENOENT)) {
d1681e
+                        mdc_inode_iatt_invalidate (this, local->loc.parent);
d1681e
+                }
d1681e
+
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         if (local->loc.parent) {
d1681e
                 mdc_inode_iatt_set (this, local->loc.parent, postparent);
d1681e
@@ -1774,8 +2003,14 @@ mdc_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
 
d1681e
         local = frame->local;
d1681e
 
d1681e
-        if (op_ret || !local)
d1681e
+        if (!local)
d1681e
+                goto out;
d1681e
+
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ESTALE) || (op_errno == ENOENT))
d1681e
+                        mdc_inode_iatt_invalidate (this, local->loc.inode);
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         if (local->fd->flags & O_TRUNC) {
d1681e
                 /* O_TRUNC modifies file size. Hence invalidate the
d1681e
@@ -1821,12 +2056,14 @@ mdc_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
         mdc_local_t  *local = NULL;
d1681e
 
d1681e
         local = frame->local;
d1681e
-
d1681e
-        if (op_ret < 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret < 0) {
d1681e
+                if ((op_errno == ENOENT) || (op_errno == ESTALE))
d1681e
+                        mdc_inode_iatt_invalidate (this, local->fd->inode);
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         mdc_inode_iatt_set (this, local->fd->inode, stbuf);
d1681e
 
d1681e
@@ -1863,12 +2100,14 @@ mdc_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
         mdc_local_t  *local = NULL;
d1681e
 
d1681e
         local = frame->local;
d1681e
-
d1681e
-        if (op_ret == -1)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret == -1) {
d1681e
+                if ((op_errno == ENOENT) || (op_errno == ESTALE))
d1681e
+                        mdc_inode_iatt_invalidate (this, local->fd->inode);
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         mdc_inode_iatt_set_validate(this, local->fd->inode, prebuf, postbuf,
d1681e
                                     _gf_true);
d1681e
@@ -1952,12 +2191,14 @@ mdc_fsetattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
         mdc_local_t  *local = NULL;
d1681e
 
d1681e
         local = frame->local;
d1681e
-
d1681e
-        if (op_ret != 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ESTALE) || (op_errno == ENOENT))
d1681e
+                        mdc_inode_iatt_invalidate (this, local->fd->inode);
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         mdc_inode_iatt_set_validate(this, local->fd->inode, prebuf, postbuf,
d1681e
                                     _gf_true);
d1681e
@@ -1995,12 +2236,14 @@ mdc_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
         mdc_local_t  *local = NULL;
d1681e
 
d1681e
         local = frame->local;
d1681e
-
d1681e
-        if (op_ret != 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ENOENT) || (op_errno == ESTALE))
d1681e
+                        mdc_inode_iatt_invalidate (this, local->fd->inode);
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         mdc_inode_iatt_set_validate(this, local->fd->inode, prebuf, postbuf,
d1681e
                                      _gf_true);
d1681e
@@ -2037,12 +2280,14 @@ mdc_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
         mdc_local_t  *local = NULL;
d1681e
 
d1681e
         local = frame->local;
d1681e
-
d1681e
-        if (op_ret != 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ENOENT) || (op_errno == ESTALE))
d1681e
+                        mdc_inode_iatt_invalidate (this, local->loc.inode);
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         mdc_inode_xatt_update (this, local->loc.inode, local->xattr);
d1681e
 
d1681e
@@ -2080,12 +2325,14 @@ mdc_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
         mdc_local_t  *local = NULL;
d1681e
 
d1681e
         local = frame->local;
d1681e
-
d1681e
-        if (op_ret != 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ESTALE) || (op_errno == ENOENT))
d1681e
+                        mdc_inode_iatt_invalidate (this, local->fd->inode);
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         mdc_inode_xatt_update (this, local->fd->inode, local->xattr);
d1681e
 
d1681e
@@ -2121,13 +2368,16 @@ mdc_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
 {
d1681e
         mdc_local_t  *local = NULL;
d1681e
 
d1681e
-        if (op_ret < 0)
d1681e
-                goto out;
d1681e
-
d1681e
         local = frame->local;
d1681e
         if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
+        if (op_ret < 0) {
d1681e
+                if ((op_errno == ENOENT) || (op_errno == ESTALE))
d1681e
+                        mdc_inode_iatt_invalidate (this, local->loc.inode);
d1681e
+                goto out;
d1681e
+        }
d1681e
+
d1681e
         mdc_inode_xatt_update (this, local->loc.inode, xattr);
d1681e
 
d1681e
 out:
d1681e
@@ -2186,13 +2436,16 @@ mdc_fgetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
 {
d1681e
         mdc_local_t  *local = NULL;
d1681e
 
d1681e
-        if (op_ret < 0)
d1681e
-                goto out;
d1681e
-
d1681e
         local = frame->local;
d1681e
         if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
+        if (op_ret < 0) {
d1681e
+                if ((op_errno == ENOENT) || (op_errno == ESTALE))
d1681e
+                        mdc_inode_iatt_invalidate (this, local->fd->inode);
d1681e
+                goto out;
d1681e
+        }
d1681e
+
d1681e
         mdc_inode_xatt_update (this, local->fd->inode, xattr);
d1681e
 
d1681e
 out:
d1681e
@@ -2250,12 +2503,14 @@ mdc_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
         mdc_local_t  *local = NULL;
d1681e
 
d1681e
         local = frame->local;
d1681e
-
d1681e
-        if (op_ret != 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ENOENT) || (op_errno == ESTALE))
d1681e
+                        mdc_inode_iatt_invalidate (this, local->loc.inode);
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
 	if (local->key)
d1681e
 		mdc_inode_xatt_unset (this, local->loc.inode, local->key);
d1681e
@@ -2319,12 +2574,14 @@ mdc_fremovexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
         mdc_local_t  *local = NULL;
d1681e
 
d1681e
         local = frame->local;
d1681e
-
d1681e
-        if (op_ret != 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ENOENT) || (op_errno == ESTALE))
d1681e
+                        mdc_inode_iatt_invalidate (this, local->fd->inode);
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
 	if (local->key)
d1681e
 		mdc_inode_xatt_unset (this, local->fd->inode, local->key);
d1681e
@@ -2379,6 +2636,28 @@ uncached:
d1681e
         return 0;
d1681e
 }
d1681e
 
d1681e
+int32_t
d1681e
+mdc_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
+                 int32_t op_ret, int32_t op_errno, fd_t *fd,
d1681e
+                 dict_t *xdata)
d1681e
+{
d1681e
+        mdc_local_t *local = NULL;
d1681e
+
d1681e
+        local = frame->local;
d1681e
+        if (!local)
d1681e
+                goto out;
d1681e
+
d1681e
+        if (op_ret == 0)
d1681e
+                goto out;
d1681e
+
d1681e
+        if ((op_errno == ESTALE) || (op_errno == ENOENT))
d1681e
+                mdc_inode_iatt_invalidate (this, local->loc.inode);
d1681e
+
d1681e
+out:
d1681e
+        MDC_STACK_UNWIND (opendir, frame, op_ret, op_errno, fd, xdata);
d1681e
+        return 0;
d1681e
+}
d1681e
+
d1681e
 
d1681e
 int
d1681e
 mdc_opendir(call_frame_t *frame, xlator_t *this, loc_t *loc,
d1681e
@@ -2387,6 +2666,11 @@ mdc_opendir(call_frame_t *frame, xlator_t *this, loc_t *loc,
d1681e
         int          ret = -1;
d1681e
         char        *mdc_key_names = NULL;
d1681e
         dict_t      *xattr_alloc = NULL;
d1681e
+        mdc_local_t *local       = NULL;
d1681e
+
d1681e
+        local = mdc_local_get (frame);
d1681e
+
d1681e
+	loc_copy (&local->loc, loc);
d1681e
 
d1681e
         if (!xdata)
d1681e
                 xdata = xattr_alloc = dict_new ();
d1681e
@@ -2404,7 +2688,7 @@ mdc_opendir(call_frame_t *frame, xlator_t *this, loc_t *loc,
d1681e
         }
d1681e
 
d1681e
 wind:
d1681e
-        STACK_WIND (frame, default_opendir_cbk, FIRST_CHILD(this),
d1681e
+        STACK_WIND (frame, mdc_opendir_cbk, FIRST_CHILD(this),
d1681e
                     FIRST_CHILD(this)->fops->opendir, loc, fd, xdata);
d1681e
 
d1681e
         if (xattr_alloc)
d1681e
@@ -2418,10 +2702,19 @@ int
d1681e
 mdc_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
 		  int op_ret, int op_errno, gf_dirent_t *entries, dict_t *xdata)
d1681e
 {
d1681e
-        gf_dirent_t *entry      = NULL;
d1681e
+        gf_dirent_t *entry = NULL;
d1681e
+        mdc_local_t *local = NULL;
d1681e
+
d1681e
+        local = frame->local;
d1681e
+        if (!local)
d1681e
+                goto unwind;
d1681e
 
d1681e
-	if (op_ret <= 0)
d1681e
+	if (op_ret <= 0) {
d1681e
+                if ((op_ret == -1) && ((op_errno == ENOENT)
d1681e
+                                       || (op_errno == ESTALE)))
d1681e
+                    mdc_inode_iatt_invalidate (this, local->fd->inode);
d1681e
 		goto unwind;
d1681e
+        }
d1681e
 
d1681e
         list_for_each_entry (entry, &entries->list, list) {
d1681e
                 if (!entry->inode)
d1681e
@@ -2431,7 +2724,7 @@ mdc_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
         }
d1681e
 
d1681e
 unwind:
d1681e
-	STACK_UNWIND_STRICT (readdirp, frame, op_ret, op_errno, entries, xdata);
d1681e
+	MDC_STACK_UNWIND (readdirp, frame, op_ret, op_errno, entries, xdata);
d1681e
 	return 0;
d1681e
 }
d1681e
 
d1681e
@@ -2440,7 +2733,14 @@ int
d1681e
 mdc_readdirp (call_frame_t *frame, xlator_t *this, fd_t *fd,
d1681e
 	      size_t size, off_t offset, dict_t *xdata)
d1681e
 {
d1681e
-	dict_t *xattr_alloc = NULL;
d1681e
+	dict_t      *xattr_alloc = NULL;
d1681e
+        mdc_local_t *local       = NULL;
d1681e
+
d1681e
+        local = mdc_local_get (frame);
d1681e
+        if (!local)
d1681e
+                goto out;
d1681e
+
d1681e
+        local->fd = fd_ref (fd);
d1681e
 
d1681e
 	if (!xdata)
d1681e
 		xdata = xattr_alloc = dict_new ();
d1681e
@@ -2453,13 +2753,28 @@ mdc_readdirp (call_frame_t *frame, xlator_t *this, fd_t *fd,
d1681e
 	if (xattr_alloc)
d1681e
 		dict_unref (xattr_alloc);
d1681e
 	return 0;
d1681e
+out:
d1681e
+        STACK_UNWIND_STRICT (readdirp, frame, -1, ENOMEM, NULL, NULL);
d1681e
+        return 0;
d1681e
 }
d1681e
 
d1681e
 int
d1681e
 mdc_readdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
d1681e
 		int op_errno, gf_dirent_t *entries, dict_t *xdata)
d1681e
 {
d1681e
-	STACK_UNWIND_STRICT (readdir, frame, op_ret, op_errno, entries, xdata);
d1681e
+        mdc_local_t *local = NULL;
d1681e
+
d1681e
+        local = frame->local;
d1681e
+        if (!local)
d1681e
+                goto out;
d1681e
+
d1681e
+        if (op_ret == 0)
d1681e
+                goto out;
d1681e
+
d1681e
+        if ((op_errno == ESTALE) || (op_errno == ENOENT))
d1681e
+                mdc_inode_iatt_invalidate (this, local->fd->inode);
d1681e
+out:
d1681e
+        MDC_STACK_UNWIND (readdir, frame, op_ret, op_errno, entries, xdata);
d1681e
 	return 0;
d1681e
 }
d1681e
 
d1681e
@@ -2467,8 +2782,15 @@ int
d1681e
 mdc_readdir (call_frame_t *frame, xlator_t *this, fd_t *fd,
d1681e
 	     size_t size, off_t offset, dict_t *xdata)
d1681e
 {
d1681e
-        int need_unref = 0;
d1681e
-	struct mdc_conf *conf = this->private;
d1681e
+        int              need_unref = 0;
d1681e
+        mdc_local_t     *local      = NULL;
d1681e
+	struct mdc_conf *conf       = this->private;
d1681e
+
d1681e
+        local = mdc_local_get (frame);
d1681e
+        if (!local)
d1681e
+                goto unwind;
d1681e
+
d1681e
+        local->fd = fd_ref (fd);
d1681e
 
d1681e
 	if (!conf->force_readdirp) {
d1681e
 		STACK_WIND(frame, mdc_readdir_cbk, FIRST_CHILD(this),
d1681e
@@ -2493,6 +2815,9 @@ mdc_readdir (call_frame_t *frame, xlator_t *this, fd_t *fd,
d1681e
                 dict_unref (xdata);
d1681e
 
d1681e
 	return 0;
d1681e
+unwind:
d1681e
+        MDC_STACK_UNWIND (readdir, frame, -1, ENOMEM, NULL, NULL);
d1681e
+        return 0;
d1681e
 }
d1681e
 
d1681e
 int
d1681e
@@ -2503,12 +2828,14 @@ mdc_fallocate_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
         mdc_local_t  *local = NULL;
d1681e
 
d1681e
         local = frame->local;
d1681e
-
d1681e
-        if (op_ret != 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ENOENT) || (op_errno == ESTALE))
d1681e
+                        mdc_inode_iatt_invalidate (this, local->fd->inode);
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         mdc_inode_iatt_set_validate(this, local->fd->inode, prebuf, postbuf,
d1681e
                                     _gf_true);
d1681e
@@ -2543,12 +2870,14 @@ mdc_discard_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
         mdc_local_t  *local = NULL;
d1681e
 
d1681e
         local = frame->local;
d1681e
-
d1681e
-        if (op_ret != 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ENOENT) || (op_errno == ESTALE))
d1681e
+                        mdc_inode_iatt_invalidate (this, local->fd->inode);
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         mdc_inode_iatt_set_validate(this, local->fd->inode, prebuf, postbuf,
d1681e
                                     _gf_true);
d1681e
@@ -2583,12 +2912,14 @@ mdc_zerofill_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
         mdc_local_t  *local = NULL;
d1681e
 
d1681e
         local = frame->local;
d1681e
-
d1681e
-        if (op_ret != 0)
d1681e
+        if (!local)
d1681e
                 goto out;
d1681e
 
d1681e
-        if (!local)
d1681e
+        if (op_ret != 0) {
d1681e
+                if ((op_errno == ENOENT) || (op_errno == ESTALE))
d1681e
+                        mdc_inode_iatt_invalidate (this, local->fd->inode);
d1681e
                 goto out;
d1681e
+        }
d1681e
 
d1681e
         mdc_inode_iatt_set_validate(this, local->fd->inode, prebuf, postbuf,
d1681e
                                     _gf_true);
d1681e
@@ -2615,6 +2946,137 @@ int mdc_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset,
d1681e
         return 0;
d1681e
 }
d1681e
 
d1681e
+int32_t
d1681e
+mdc_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
+                  int32_t op_ret, int32_t op_errno, const char *path,
d1681e
+                  struct iatt *buf, dict_t *xdata)
d1681e
+{
d1681e
+        mdc_local_t *local = NULL;
d1681e
+
d1681e
+        local = frame->local;
d1681e
+        if (!local)
d1681e
+                goto out;
d1681e
+
d1681e
+        if (op_ret == 0)
d1681e
+                goto out;
d1681e
+
d1681e
+        if ((op_errno == ENOENT) || (op_errno == ESTALE))
d1681e
+                mdc_inode_iatt_invalidate (this, local->loc.inode);
d1681e
+
d1681e
+out:
d1681e
+	MDC_STACK_UNWIND (readlink, frame, op_ret, op_errno,
d1681e
+                          path, buf, xdata);
d1681e
+	return 0;
d1681e
+}
d1681e
+
d1681e
+int32_t
d1681e
+mdc_readlink (call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size,
d1681e
+              dict_t *xdata)
d1681e
+{
d1681e
+        mdc_local_t *local = NULL;
d1681e
+
d1681e
+        local = mdc_local_get (frame);
d1681e
+        if (!local)
d1681e
+                goto unwind;
d1681e
+
d1681e
+        loc_copy (&local->loc, loc);
d1681e
+
d1681e
+	STACK_WIND (frame, mdc_readlink_cbk, FIRST_CHILD(this),
d1681e
+                    FIRST_CHILD(this)->fops->readlink,
d1681e
+                    loc, size, xdata);
d1681e
+	return 0;
d1681e
+
d1681e
+unwind:
d1681e
+        MDC_STACK_UNWIND (readlink, frame, -1, ENOMEM, NULL, NULL, NULL);
d1681e
+        return 0;
d1681e
+}
d1681e
+
d1681e
+int32_t
d1681e
+mdc_fsyncdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
+                  int32_t op_ret, int32_t op_errno, dict_t *xdata)
d1681e
+{
d1681e
+        mdc_local_t *local = NULL;
d1681e
+
d1681e
+        local = frame->local;
d1681e
+        if (!local)
d1681e
+                goto out;
d1681e
+
d1681e
+        if (op_ret == 0)
d1681e
+                goto out;
d1681e
+
d1681e
+        if ((op_errno == ESTALE) || (op_errno == ENOENT))
d1681e
+                mdc_inode_iatt_invalidate (this, local->fd->inode);
d1681e
+
d1681e
+out:
d1681e
+	MDC_STACK_UNWIND (fsyncdir, frame, op_ret, op_errno, xdata);
d1681e
+	return 0;
d1681e
+}
d1681e
+
d1681e
+int32_t
d1681e
+mdc_fsyncdir (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags,
d1681e
+              dict_t *xdata)
d1681e
+{
d1681e
+        mdc_local_t *local = NULL;
d1681e
+
d1681e
+        local = mdc_local_get (frame);
d1681e
+        if (!local)
d1681e
+                goto unwind;
d1681e
+
d1681e
+        local->fd = fd_ref (fd);
d1681e
+
d1681e
+	STACK_WIND (frame, mdc_fsyncdir_cbk, FIRST_CHILD(this),
d1681e
+                    FIRST_CHILD(this)->fops->fsyncdir, fd, flags, xdata);
d1681e
+	return 0;
d1681e
+
d1681e
+unwind:
d1681e
+        MDC_STACK_UNWIND (fsyncdir, frame, -1, ENOMEM, NULL);
d1681e
+        return 0;
d1681e
+}
d1681e
+
d1681e
+int32_t
d1681e
+mdc_access_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
d1681e
+                int32_t op_ret, int32_t op_errno, dict_t *xdata)
d1681e
+{
d1681e
+        mdc_local_t *local = NULL;
d1681e
+
d1681e
+        local = frame->local;
d1681e
+        if (!local)
d1681e
+                goto out;
d1681e
+
d1681e
+        if (op_ret == 0)
d1681e
+                goto out;
d1681e
+
d1681e
+        if ((op_errno == ESTALE) || (op_errno == ENOENT))
d1681e
+                mdc_inode_iatt_invalidate (this, local->loc.inode);
d1681e
+
d1681e
+out:
d1681e
+	MDC_STACK_UNWIND (access, frame, op_ret, op_errno, xdata);
d1681e
+	return 0;
d1681e
+}
d1681e
+
d1681e
+
d1681e
+
d1681e
+int32_t
d1681e
+mdc_access (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t mask,
d1681e
+            dict_t *xdata)
d1681e
+{
d1681e
+        mdc_local_t *local = NULL;
d1681e
+
d1681e
+        local = mdc_local_get (frame);
d1681e
+        if (!local)
d1681e
+                goto unwind;
d1681e
+
d1681e
+        loc_copy (&local->loc, loc);
d1681e
+
d1681e
+	STACK_WIND (frame, mdc_access_cbk, FIRST_CHILD(this),
d1681e
+                    FIRST_CHILD(this)->fops->access, loc, mask, xdata);
d1681e
+	return 0;
d1681e
+
d1681e
+unwind:
d1681e
+        MDC_STACK_UNWIND (access, frame, -1, ENOMEM, NULL);
d1681e
+	return 0;
d1681e
+}
d1681e
+
d1681e
 
d1681e
 int
d1681e
 mdc_priv_dump (xlator_t *this)
d1681e
@@ -3150,6 +3612,10 @@ struct xlator_fops fops = {
d1681e
 	.fallocate   = mdc_fallocate,
d1681e
 	.discard     = mdc_discard,
d1681e
         .zerofill    = mdc_zerofill,
d1681e
+        .statfs      = mdc_statfs,
d1681e
+        .readlink    = mdc_readlink,
d1681e
+        .fsyncdir    = mdc_fsyncdir,
d1681e
+        .access      = mdc_access,
d1681e
 };
d1681e
 
d1681e
 
d1681e
-- 
d1681e
1.8.3.1
d1681e