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