9f5ccc
From ddb0038de77a4269fa7eed1bb217bfb6bed1b7ba Mon Sep 17 00:00:00 2001
9f5ccc
From: N Balachandran <nbalacha@redhat.com>
9f5ccc
Date: Fri, 9 Aug 2019 14:34:22 +0530
9f5ccc
Subject: [PATCH 337/344] fuse: Set limit on invalidate queue size
9f5ccc
9f5ccc
If the glusterfs fuse client process is unable to
9f5ccc
process the invalidate requests quickly enough, the
9f5ccc
number of such requests quickly grows large enough
9f5ccc
to use a significant amount of memory.
9f5ccc
We are now introducing another option to set an upper
9f5ccc
limit on these to prevent runaway memory usage.
9f5ccc
9f5ccc
> Upstream https://review.gluster.org/23187
9f5ccc
> Change-Id: Iddfff1ee2de1466223e6717f7abd4b28ed947788
9f5ccc
> Fixes: bz#1732717
9f5ccc
> Signed-off-by: N Balachandran <nbalacha@redhat.com>
9f5ccc
9f5ccc
BUG: 1763208
9f5ccc
Change-Id: I666cdf6c70999a0f0bc79969e8df0a9dde93b6e4
9f5ccc
Signed-off-by: Csaba Henk <csaba@redhat.com>
9f5ccc
Reviewed-on: https://code.engineering.redhat.com/gerrit/187529
9f5ccc
Tested-by: RHGS Build Bot <nigelb@redhat.com>
9f5ccc
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
9f5ccc
---
9f5ccc
 doc/mount.glusterfs.8                       |  5 +++
9f5ccc
 glusterfsd/src/glusterfsd.c                 | 21 ++++++++++
9f5ccc
 glusterfsd/src/glusterfsd.h                 |  3 +-
9f5ccc
 libglusterfs/src/glusterfs/glusterfs.h      |  1 +
9f5ccc
 libglusterfs/src/glusterfs/inode.h          |  1 +
9f5ccc
 libglusterfs/src/inode.c                    | 31 +++++++++++----
9f5ccc
 xlators/mount/fuse/src/fuse-bridge.c        | 60 ++++++++++++++++++++++-------
9f5ccc
 xlators/mount/fuse/src/fuse-bridge.h        |  3 +-
9f5ccc
 xlators/mount/fuse/utils/mount.glusterfs.in |  7 ++++
9f5ccc
 9 files changed, 108 insertions(+), 24 deletions(-)
9f5ccc
9f5ccc
diff --git a/doc/mount.glusterfs.8 b/doc/mount.glusterfs.8
9f5ccc
index 286631b..b35b362 100644
9f5ccc
--- a/doc/mount.glusterfs.8
9f5ccc
+++ b/doc/mount.glusterfs.8
9f5ccc
@@ -126,6 +126,11 @@ Provide list of backup volfile servers in the following format [default: None]
9f5ccc
 Set fuse module's limit for number of inodes kept in LRU list to N [default: 131072]
9f5ccc
 .TP
9f5ccc
 .TP
9f5ccc
+\fBinvalidate-limit=\fRN
9f5ccc
+Suspend fuse invalidations implied by 'lru-limit' if  number of outstanding
9f5ccc
+invalidations reaches N
9f5ccc
+.TP
9f5ccc
+.TP
9f5ccc
 \fBbackground-qlen=\fRN
9f5ccc
 Set fuse module's background queue length to N [default: 64]
9f5ccc
 .TP
9f5ccc
diff --git a/glusterfsd/src/glusterfsd.c b/glusterfsd/src/glusterfsd.c
9f5ccc
index 5b5e996..0856471 100644
9f5ccc
--- a/glusterfsd/src/glusterfsd.c
9f5ccc
+++ b/glusterfsd/src/glusterfsd.c
9f5ccc
@@ -212,6 +212,9 @@ static struct argp_option gf_options[] = {
9f5ccc
     {"lru-limit", ARGP_FUSE_LRU_LIMIT_KEY, "N", 0,
9f5ccc
      "Set fuse module's limit for number of inodes kept in LRU list to N "
9f5ccc
      "[default: 131072]"},
9f5ccc
+    {"invalidate-limit", ARGP_FUSE_INVALIDATE_LIMIT_KEY, "N", 0,
9f5ccc
+     "Suspend inode invalidations implied by 'lru-limit' if the number of "
9f5ccc
+     "outstanding invalidations reaches N"},
9f5ccc
     {"background-qlen", ARGP_FUSE_BACKGROUND_QLEN_KEY, "N", 0,
9f5ccc
      "Set fuse module's background queue length to N "
9f5ccc
      "[default: 64]"},
9f5ccc
@@ -504,6 +507,16 @@ set_fuse_mount_options(glusterfs_ctx_t *ctx, dict_t *options)
9f5ccc
         }
9f5ccc
     }
9f5ccc
 
9f5ccc
+    if (cmd_args->invalidate_limit >= 0) {
9f5ccc
+        ret = dict_set_int32(options, "invalidate-limit",
9f5ccc
+                             cmd_args->invalidate_limit);
9f5ccc
+        if (ret < 0) {
9f5ccc
+            gf_msg("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_4,
9f5ccc
+                   "invalidate-limit");
9f5ccc
+            goto err;
9f5ccc
+        }
9f5ccc
+    }
9f5ccc
+
9f5ccc
     if (cmd_args->background_qlen) {
9f5ccc
         ret = dict_set_int32(options, "background-qlen",
9f5ccc
                              cmd_args->background_qlen);
9f5ccc
@@ -1283,6 +1296,14 @@ parse_opts(int key, char *arg, struct argp_state *state)
9f5ccc
             argp_failure(state, -1, 0, "unknown LRU limit option %s", arg);
9f5ccc
             break;
9f5ccc
 
9f5ccc
+        case ARGP_FUSE_INVALIDATE_LIMIT_KEY:
9f5ccc
+            if (!gf_string2int32(arg, &cmd_args->invalidate_limit))
9f5ccc
+                break;
9f5ccc
+
9f5ccc
+            argp_failure(state, -1, 0, "unknown invalidate limit option %s",
9f5ccc
+                         arg);
9f5ccc
+            break;
9f5ccc
+
9f5ccc
         case ARGP_FUSE_BACKGROUND_QLEN_KEY:
9f5ccc
             if (!gf_string2int(arg, &cmd_args->background_qlen))
9f5ccc
                 break;
9f5ccc
diff --git a/glusterfsd/src/glusterfsd.h b/glusterfsd/src/glusterfsd.h
9f5ccc
index fa55789..ee655f0 100644
9f5ccc
--- a/glusterfsd/src/glusterfsd.h
9f5ccc
+++ b/glusterfsd/src/glusterfsd.h
9f5ccc
@@ -111,7 +111,8 @@ enum argp_option_keys {
9f5ccc
     ARGP_FUSE_FLUSH_HANDLE_INTERRUPT_KEY = 189,
9f5ccc
     ARGP_FUSE_LRU_LIMIT_KEY = 190,
9f5ccc
     ARGP_FUSE_AUTO_INVAL_KEY = 191,
9f5ccc
-    ARGP_BRICK_MUX_KEY = 192
9f5ccc
+    ARGP_BRICK_MUX_KEY = 192,
9f5ccc
+    ARGP_FUSE_INVALIDATE_LIMIT_KEY = 195,
9f5ccc
 };
9f5ccc
 
9f5ccc
 struct _gfd_vol_top_priv {
9f5ccc
diff --git a/libglusterfs/src/glusterfs/glusterfs.h b/libglusterfs/src/glusterfs/glusterfs.h
9f5ccc
index 79c93ae..3b594c0 100644
9f5ccc
--- a/libglusterfs/src/glusterfs/glusterfs.h
9f5ccc
+++ b/libglusterfs/src/glusterfs/glusterfs.h
9f5ccc
@@ -541,6 +541,7 @@ struct _cmd_args {
9f5ccc
     int client_pid_set;
9f5ccc
     unsigned uid_map_root;
9f5ccc
     int32_t lru_limit;
9f5ccc
+    int32_t invalidate_limit;
9f5ccc
     int background_qlen;
9f5ccc
     int congestion_threshold;
9f5ccc
     char *fuse_mountopts;
9f5ccc
diff --git a/libglusterfs/src/glusterfs/inode.h b/libglusterfs/src/glusterfs/inode.h
9f5ccc
index 52efdd8..4421c47 100644
9f5ccc
--- a/libglusterfs/src/glusterfs/inode.h
9f5ccc
+++ b/libglusterfs/src/glusterfs/inode.h
9f5ccc
@@ -107,6 +107,7 @@ struct _inode {
9f5ccc
     struct list_head list;        /* active/lru/purge */
9f5ccc
 
9f5ccc
     struct _inode_ctx *_ctx; /* replacement for dict_t *(inode->ctx) */
9f5ccc
+    bool in_invalidate_list; /* Set if inode is in table invalidate list */
9f5ccc
     bool invalidate_sent;    /* Set it if invalidator_fn is called for inode */
9f5ccc
 };
9f5ccc
 
9f5ccc
diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c
9f5ccc
index 96ddea5..5331e93 100644
9f5ccc
--- a/libglusterfs/src/inode.c
9f5ccc
+++ b/libglusterfs/src/inode.c
9f5ccc
@@ -558,8 +558,8 @@ __inode_unref(inode_t *inode, bool clear)
9f5ccc
 
9f5ccc
     this = THIS;
9f5ccc
 
9f5ccc
-    if (clear && inode->invalidate_sent) {
9f5ccc
-        inode->invalidate_sent = false;
9f5ccc
+    if (clear && inode->in_invalidate_list) {
9f5ccc
+        inode->in_invalidate_list = false;
9f5ccc
         inode->table->invalidate_size--;
9f5ccc
         __inode_activate(inode);
9f5ccc
     }
9f5ccc
@@ -573,7 +573,7 @@ __inode_unref(inode_t *inode, bool clear)
9f5ccc
         inode->_ctx[index].ref--;
9f5ccc
     }
9f5ccc
 
9f5ccc
-    if (!inode->ref && !inode->invalidate_sent) {
9f5ccc
+    if (!inode->ref && !inode->in_invalidate_list) {
9f5ccc
         inode->table->active_size--;
9f5ccc
 
9f5ccc
         nlookup = GF_ATOMIC_GET(inode->nlookup);
9f5ccc
@@ -609,14 +609,14 @@ __inode_ref(inode_t *inode, bool is_invalidate)
9f5ccc
         return inode;
9f5ccc
 
9f5ccc
     if (!inode->ref) {
9f5ccc
-        if (inode->invalidate_sent) {
9f5ccc
-            inode->invalidate_sent = false;
9f5ccc
+        if (inode->in_invalidate_list) {
9f5ccc
+            inode->in_invalidate_list = false;
9f5ccc
             inode->table->invalidate_size--;
9f5ccc
         } else {
9f5ccc
             inode->table->lru_size--;
9f5ccc
         }
9f5ccc
         if (is_invalidate) {
9f5ccc
-            inode->invalidate_sent = true;
9f5ccc
+            inode->in_invalidate_list = true;
9f5ccc
             inode->table->invalidate_size++;
9f5ccc
             list_move_tail(&inode->list, &inode->table->invalidate);
9f5ccc
         } else {
9f5ccc
@@ -1609,6 +1609,7 @@ static int
9f5ccc
 inode_table_prune(inode_table_t *table)
9f5ccc
 {
9f5ccc
     int ret = 0;
9f5ccc
+    int ret1 = 0;
9f5ccc
     struct list_head purge = {
9f5ccc
         0,
9f5ccc
     };
9f5ccc
@@ -1647,6 +1648,10 @@ inode_table_prune(inode_table_t *table)
9f5ccc
                 /* check for valid inode with 'nlookup' */
9f5ccc
                 nlookup = GF_ATOMIC_GET(entry->nlookup);
9f5ccc
                 if (nlookup) {
9f5ccc
+                    if (entry->invalidate_sent) {
9f5ccc
+                        list_move_tail(&entry->list, &table->lru);
9f5ccc
+                        continue;
9f5ccc
+                    }
9f5ccc
                     __inode_ref(entry, true);
9f5ccc
                     tmp = entry;
9f5ccc
                     break;
9f5ccc
@@ -1668,9 +1673,19 @@ inode_table_prune(inode_table_t *table)
9f5ccc
     if (tmp) {
9f5ccc
         xlator_t *old_THIS = THIS;
9f5ccc
         THIS = table->invalidator_xl;
9f5ccc
-        table->invalidator_fn(table->invalidator_xl, tmp);
9f5ccc
+        ret1 = table->invalidator_fn(table->invalidator_xl, tmp);
9f5ccc
         THIS = old_THIS;
9f5ccc
-        inode_unref(tmp);
9f5ccc
+        pthread_mutex_lock(&table->lock);
9f5ccc
+        {
9f5ccc
+            if (!ret1) {
9f5ccc
+                tmp->invalidate_sent = true;
9f5ccc
+                __inode_unref(tmp, false);
9f5ccc
+            } else {
9f5ccc
+                /* Move this back to the lru list*/
9f5ccc
+                __inode_unref(tmp, true);
9f5ccc
+            }
9f5ccc
+        }
9f5ccc
+        pthread_mutex_unlock(&table->lock);
9f5ccc
     }
9f5ccc
 
9f5ccc
     /* Just so that if purge list is handled too, then clear it off */
9f5ccc
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c
9f5ccc
index 1c946a2..8b2e7f0 100644
9f5ccc
--- a/xlators/mount/fuse/src/fuse-bridge.c
9f5ccc
+++ b/xlators/mount/fuse/src/fuse-bridge.c
9f5ccc
@@ -26,7 +26,7 @@ static int gf_fuse_xattr_enotsup_log;
9f5ccc
 void
9f5ccc
 fini(xlator_t *this_xl);
9f5ccc
 
9f5ccc
-static void
9f5ccc
+static int32_t
9f5ccc
 fuse_invalidate_inode(xlator_t *this, uint64_t fuse_ino);
9f5ccc
 
9f5ccc
 /*
9f5ccc
@@ -312,7 +312,7 @@ send_fuse_data(xlator_t *this, fuse_in_header_t *finh, void *data, size_t size)
9f5ccc
 #define send_fuse_obj(this, finh, obj)                                         \
9f5ccc
     send_fuse_data(this, finh, obj, sizeof(*(obj)))
9f5ccc
 
9f5ccc
-static void
9f5ccc
+static int32_t
9f5ccc
 fuse_invalidate_entry(xlator_t *this, uint64_t fuse_ino)
9f5ccc
 {
9f5ccc
 #if FUSE_KERNEL_MINOR_VERSION >= 11
9f5ccc
@@ -328,17 +328,22 @@ fuse_invalidate_entry(xlator_t *this, uint64_t fuse_ino)
9f5ccc
 
9f5ccc
     priv = this->private;
9f5ccc
     if (!priv->reverse_fuse_thread_started)
9f5ccc
-        return;
9f5ccc
+        return -1;
9f5ccc
+
9f5ccc
+    if (priv->invalidate_limit &&
9f5ccc
+        (priv->invalidate_count >= priv->invalidate_limit)) {
9f5ccc
+        return -1;
9f5ccc
+    }
9f5ccc
 
9f5ccc
     inode = (inode_t *)(unsigned long)fuse_ino;
9f5ccc
     if (inode == NULL)
9f5ccc
-        return;
9f5ccc
+        return -1;
9f5ccc
 
9f5ccc
     list_for_each_entry_safe(dentry, tmp, &inode->dentry_list, inode_list)
9f5ccc
     {
9f5ccc
         node = GF_CALLOC(1, sizeof(*node), gf_fuse_mt_invalidate_node_t);
9f5ccc
         if (node == NULL)
9f5ccc
-            break;
9f5ccc
+            return -1;
9f5ccc
 
9f5ccc
         INIT_LIST_HEAD(&node->next);
9f5ccc
 
9f5ccc
@@ -375,20 +380,21 @@ fuse_invalidate_entry(xlator_t *this, uint64_t fuse_ino)
9f5ccc
         pthread_mutex_lock(&priv->invalidate_mutex);
9f5ccc
         {
9f5ccc
             list_add_tail(&node->next, &priv->invalidate_list);
9f5ccc
+            priv->invalidate_count++;
9f5ccc
             pthread_cond_signal(&priv->invalidate_cond);
9f5ccc
         }
9f5ccc
         pthread_mutex_unlock(&priv->invalidate_mutex);
9f5ccc
     }
9f5ccc
 
9f5ccc
 #endif
9f5ccc
-    return;
9f5ccc
+    return 0;
9f5ccc
 }
9f5ccc
 
9f5ccc
 /*
9f5ccc
  * Send an inval inode notification to fuse. This causes an invalidation of the
9f5ccc
  * entire page cache mapping on the inode.
9f5ccc
  */
9f5ccc
-static void
9f5ccc
+static int32_t
9f5ccc
 fuse_invalidate_inode(xlator_t *this, uint64_t fuse_ino)
9f5ccc
 {
9f5ccc
 #if FUSE_KERNEL_MINOR_VERSION >= 11
9f5ccc
@@ -401,15 +407,20 @@ fuse_invalidate_inode(xlator_t *this, uint64_t fuse_ino)
9f5ccc
     priv = this->private;
9f5ccc
 
9f5ccc
     if (!priv->reverse_fuse_thread_started)
9f5ccc
-        return;
9f5ccc
+        return -1;
9f5ccc
+
9f5ccc
+    if (priv->invalidate_limit &&
9f5ccc
+        (priv->invalidate_count >= priv->invalidate_limit)) {
9f5ccc
+        return -1;
9f5ccc
+    }
9f5ccc
 
9f5ccc
     inode = (inode_t *)(unsigned long)fuse_ino;
9f5ccc
     if (inode == NULL)
9f5ccc
-        return;
9f5ccc
+        return -1;
9f5ccc
 
9f5ccc
     node = GF_CALLOC(1, sizeof(*node), gf_fuse_mt_invalidate_node_t);
9f5ccc
     if (node == NULL)
9f5ccc
-        return;
9f5ccc
+        return -1;
9f5ccc
 
9f5ccc
     INIT_LIST_HEAD(&node->next);
9f5ccc
 
9f5ccc
@@ -435,6 +446,7 @@ fuse_invalidate_inode(xlator_t *this, uint64_t fuse_ino)
9f5ccc
     pthread_mutex_lock(&priv->invalidate_mutex);
9f5ccc
     {
9f5ccc
         list_add_tail(&node->next, &priv->invalidate_list);
9f5ccc
+        priv->invalidate_count++;
9f5ccc
         pthread_cond_signal(&priv->invalidate_cond);
9f5ccc
     }
9f5ccc
     pthread_mutex_unlock(&priv->invalidate_mutex);
9f5ccc
@@ -443,7 +455,7 @@ fuse_invalidate_inode(xlator_t *this, uint64_t fuse_ino)
9f5ccc
     gf_log("glusterfs-fuse", GF_LOG_WARNING,
9f5ccc
            "fuse_invalidate_inode not implemented on this system");
9f5ccc
 #endif
9f5ccc
-    return;
9f5ccc
+    return 0;
9f5ccc
 }
9f5ccc
 
9f5ccc
 #if FUSE_KERNEL_MINOR_VERSION >= 11
9f5ccc
@@ -451,8 +463,9 @@ fuse_invalidate_inode(xlator_t *this, uint64_t fuse_ino)
9f5ccc
 static int32_t
9f5ccc
 fuse_inode_invalidate_fn(xlator_t *this, inode_t *inode)
9f5ccc
 {
9f5ccc
-    fuse_invalidate_entry(this, (uint64_t)(uintptr_t)inode);
9f5ccc
-    return 0;
9f5ccc
+    int32_t ret = 0;
9f5ccc
+    ret = fuse_invalidate_entry(this, (uint64_t)(uintptr_t)inode);
9f5ccc
+    return ret;
9f5ccc
 }
9f5ccc
 #endif
9f5ccc
 
9f5ccc
@@ -4003,7 +4016,9 @@ fuse_setxattr(xlator_t *this, fuse_in_header_t *finh, void *msg,
9f5ccc
         gf_log("fuse", GF_LOG_TRACE, "got request to invalidate %" PRIu64,
9f5ccc
                finh->nodeid);
9f5ccc
 #if FUSE_KERNEL_MINOR_VERSION >= 11
9f5ccc
-        fuse_invalidate_entry(this, finh->nodeid);
9f5ccc
+        ret = fuse_invalidate_entry(this, finh->nodeid);
9f5ccc
+        if (ret)
9f5ccc
+            op_errno = EBUSY;
9f5ccc
 #endif
9f5ccc
         goto done;
9f5ccc
     }
9f5ccc
@@ -4812,6 +4827,7 @@ notify_kernel_loop(void *data)
9f5ccc
                               fuse_invalidate_node_t, next);
9f5ccc
 
9f5ccc
             list_del_init(&node->next);
9f5ccc
+            priv->invalidate_count--;
9f5ccc
         }
9f5ccc
         pthread_mutex_unlock(&priv->invalidate_mutex);
9f5ccc
 
9f5ccc
@@ -4855,6 +4871,7 @@ notify_kernel_loop(void *data)
9f5ccc
             list_del_init(&node->next);
9f5ccc
             GF_FREE(node);
9f5ccc
         }
9f5ccc
+        priv->invalidate_count = 0;
9f5ccc
     }
9f5ccc
     pthread_mutex_unlock(&priv->invalidate_mutex);
9f5ccc
 
9f5ccc
@@ -6080,6 +6097,9 @@ fuse_priv_dump(xlator_t *this)
9f5ccc
                        (int)private->timed_response_fuse_thread_started);
9f5ccc
     gf_proc_dump_write("reverse_thread_started", "%d",
9f5ccc
                        (int)private->reverse_fuse_thread_started);
9f5ccc
+    gf_proc_dump_write("invalidate_limit", "%u", private->invalidate_limit);
9f5ccc
+    gf_proc_dump_write("invalidate_queue_length", "%" PRIu64,
9f5ccc
+                       private->invalidate_count);
9f5ccc
     gf_proc_dump_write("use_readdirp", "%d", private->use_readdirp);
9f5ccc
 
9f5ccc
     return 0;
9f5ccc
@@ -6619,6 +6639,9 @@ init(xlator_t *this_xl)
9f5ccc
 
9f5ccc
     GF_OPTION_INIT("lru-limit", priv->lru_limit, uint32, cleanup_exit);
9f5ccc
 
9f5ccc
+    GF_OPTION_INIT("invalidate-limit", priv->invalidate_limit, uint32,
9f5ccc
+                   cleanup_exit);
9f5ccc
+
9f5ccc
     GF_OPTION_INIT("event-history", priv->event_history, bool, cleanup_exit);
9f5ccc
 
9f5ccc
     GF_OPTION_INIT("thin-client", priv->thin_client, bool, cleanup_exit);
9f5ccc
@@ -6955,6 +6978,15 @@ struct volume_options options[] = {
9f5ccc
                        "reaching this limit (0 means 'unlimited')",
9f5ccc
     },
9f5ccc
     {
9f5ccc
+        .key = {"invalidate-limit"},
9f5ccc
+        .type = GF_OPTION_TYPE_INT,
9f5ccc
+        .default_value = "0",
9f5ccc
+        .min = 0,
9f5ccc
+        .description = "suspend invalidations as of 'lru-limit' if the number "
9f5ccc
+                       "of outstanding invalidations reaches this limit "
9f5ccc
+                       "(0 means 'unlimited')",
9f5ccc
+    },
9f5ccc
+    {
9f5ccc
         .key = {"auto-invalidation"},
9f5ccc
         .type = GF_OPTION_TYPE_BOOL,
9f5ccc
         .default_value = "true",
9f5ccc
diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h
9f5ccc
index 697bd88..2311582 100644
9f5ccc
--- a/xlators/mount/fuse/src/fuse-bridge.h
9f5ccc
+++ b/xlators/mount/fuse/src/fuse-bridge.h
9f5ccc
@@ -139,7 +139,7 @@ struct fuse_private {
9f5ccc
     pthread_cond_t invalidate_cond;
9f5ccc
     pthread_mutex_t invalidate_mutex;
9f5ccc
     gf_boolean_t reverse_fuse_thread_started;
9f5ccc
-
9f5ccc
+    uint64_t invalidate_count;
9f5ccc
     /* For communicating with separate mount thread. */
9f5ccc
     int status_pipe[2];
9f5ccc
 
9f5ccc
@@ -191,6 +191,7 @@ struct fuse_private {
9f5ccc
 
9f5ccc
     /* LRU Limit, if not set, default is 128k for now */
9f5ccc
     uint32_t lru_limit;
9f5ccc
+    uint32_t invalidate_limit;
9f5ccc
 };
9f5ccc
 typedef struct fuse_private fuse_private_t;
9f5ccc
 
9f5ccc
diff --git a/xlators/mount/fuse/utils/mount.glusterfs.in b/xlators/mount/fuse/utils/mount.glusterfs.in
9f5ccc
index cbde42d..61d7422 100755
9f5ccc
--- a/xlators/mount/fuse/utils/mount.glusterfs.in
9f5ccc
+++ b/xlators/mount/fuse/utils/mount.glusterfs.in
9f5ccc
@@ -257,6 +257,10 @@ start_glusterfs ()
9f5ccc
         cmd_line=$(echo "$cmd_line --lru-limit=$lru_limit");
9f5ccc
     fi
9f5ccc
 
9f5ccc
+    if [ -n "$invalidate_limit" ]; then
9f5ccc
+        cmd_line=$(echo "$cmd_line --invalidate-limit=$invalidate_limit");
9f5ccc
+    fi
9f5ccc
+
9f5ccc
     if [ -n "$bg_qlen" ]; then
9f5ccc
         cmd_line=$(echo "$cmd_line --background-qlen=$bg_qlen");
9f5ccc
     fi
9f5ccc
@@ -505,6 +509,9 @@ with_options()
9f5ccc
         "lru-limit")
9f5ccc
             lru_limit=$value
9f5ccc
             ;;
9f5ccc
+        "invalidate-limit")
9f5ccc
+            invalidate_limit=$value
9f5ccc
+            ;;
9f5ccc
         "background-qlen")
9f5ccc
             bg_qlen=$value
9f5ccc
             ;;
9f5ccc
-- 
9f5ccc
1.8.3.1
9f5ccc