diff options
| author | Poornima G <pgurusid@redhat.com> | 2015-02-19 04:49:35 +0530 | 
|---|---|---|
| committer | Vijay Bellur <vbellur@redhat.com> | 2015-03-02 20:28:48 -0800 | 
| commit | 5e12c658d6c2dc92fd336b745036641f054b3a40 (patch) | |
| tree | fabceb17a37c21cddb3b245ccccda77a0a556a86 /libglusterfs/src | |
| parent | 7c44ac371cc7553bd8d29455dafc2c07cf5b96e1 (diff) | |
libglusterfs: Add inode table cleanup APIs.
Took the inode context free code from the patch
http://review.gluster.org/#/c/4775/18/libglusterfs/src/inode.c
Change-Id: I05fc025763fe4ce61dc61503de27ec1d3a203e50
BUG: 1093594
Signed-off-by: Poornima G <pgurusid@redhat.com>
Reviewed-on: http://review.gluster.org/9700
Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Diffstat (limited to 'libglusterfs/src')
| -rw-r--r-- | libglusterfs/src/inode.c | 234 | ||||
| -rw-r--r-- | libglusterfs/src/inode.h | 9 | 
2 files changed, 238 insertions, 5 deletions
diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c index 2189a032afe..a6b184fc5d9 100644 --- a/libglusterfs/src/inode.c +++ b/libglusterfs/src/inode.c @@ -135,6 +135,7 @@ __dentry_unset (dentry_t *dentry)          list_del_init (&dentry->inode_list);          GF_FREE (dentry->name); +        dentry->name = NULL;          if (dentry->parent) {                  __inode_unref (dentry->parent); @@ -294,7 +295,7 @@ __dentry_search_for_inode (inode_t *inode, uuid_t pargfid, const char *name)  static void -__inode_destroy (inode_t *inode) +__inode_ctx_free (inode_t *inode)  {          int          index = 0;          xlator_t    *xl = NULL; @@ -310,7 +311,7 @@ __inode_destroy (inode_t *inode)                  goto noctx;          } -        for (index = 0; index < inode->table->ctxcount; index++) { +        for (index = 0; index < inode->table->xl->graph->xl_count; index++) {                  if (inode->_ctx[index].xl_key) {                          xl = (xlator_t *)(long)inode->_ctx[index].xl_key;                          old_THIS = THIS; @@ -322,13 +323,27 @@ __inode_destroy (inode_t *inode)          }          GF_FREE (inode->_ctx); +        inode->_ctx = NULL; +  noctx: +        return; +} + +static void +__inode_destroy (inode_t *inode) +{ +        if (!inode) { +                gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); +                return; +        } + +        __inode_ctx_free (inode); +          LOCK_DESTROY (&inode->lock);          //  memset (inode, 0xb, sizeof (*inode));          mem_put (inode);  } -  static void  __inode_activate (inode_t *inode)  { @@ -586,6 +601,41 @@ inode_new (inode_table_t *table)  } +/* Reduce the ref count by value 'nref' + * Args: + * inode - address of the inode to operate on + * nref - number to subtracted from inode->ref + *        if nref is 0, then the ref count is overwritten 0 + * + * This function may cause the purging of the inode, + * hence to be used only in destructor functions and not otherwise. + */ +static inode_t * +__inode_ref_reduce_by_n (inode_t *inode, uint64_t nref) +{ +        if (!inode) +                return NULL; + +        GF_ASSERT (inode->ref >= nref); + +        inode->ref -= nref; + +        if (!nref) +                inode->ref = 0; + +        if (!inode->ref) { +                inode->table->active_size--; + +                if (inode->nlookup) +                        __inode_passivate (inode); +                else +                        __inode_retire (inode); +        } + +        return inode; +} + +  static inode_t *  __inode_lookup (inode_t *inode)  { @@ -968,6 +1018,30 @@ inode_lookup (inode_t *inode)  int +inode_ref_reduce_by_n (inode_t *inode, uint64_t nref) +{ +        inode_table_t *table = NULL; + +        if (!inode) { +                gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); +                return -1; +        } + +        table = inode->table; + +        pthread_mutex_lock (&table->lock); +        { +                __inode_ref_reduce_by_n (inode, nref); +        } +        pthread_mutex_unlock (&table->lock); + +        inode_table_prune (table); + +        return 0; +} + + +int  inode_forget (inode_t *inode, uint64_t nlookup)  {          inode_table_t *table = NULL; @@ -1467,6 +1541,152 @@ out:          return new;  } +int +inode_table_ctx_free (inode_table_t *table) +{ +        int ret = 0; +        inode_t *del = NULL; +        inode_t *tmp = NULL; +        int purge_count = 0; +        int lru_count = 0; +        int active_count = 0; +        xlator_t *this = NULL; +        int itable_size = 0; + +        if (!table) +                return -1; + +        this = THIS; + +        pthread_mutex_lock (&table->lock); +        { +                list_for_each_entry_safe (del, tmp, &table->purge, list) { +                        if (del->_ctx) { +                                __inode_ctx_free (del); +                                purge_count++; +                        } +                } + +                list_for_each_entry_safe (del, tmp, &table->lru, list) { +                        if (del->_ctx) { +                                __inode_ctx_free (del); +                                lru_count++; +                        } +                } + +                /* should the contexts of active inodes be freed? +                 * Since before this function being called fds would have +                 * been migrated and would have held the ref on the new +                 * inode from the new inode table, the older inode would not +                 * be used. +                 */ +                list_for_each_entry_safe (del, tmp, &table->active, list) { +                        if (del->_ctx) { +                                __inode_ctx_free (del); +                                active_count++; +                        } +                } +        } +        pthread_mutex_unlock (&table->lock); + +        ret = purge_count + lru_count + active_count; +        itable_size = table->active_size + table->lru_size + table->purge_size; +        gf_log_callingfn (this->name, GF_LOG_INFO, "total %d (itable size: %d) " +                        "inode contexts have been freed (active: %d, " +                        "(active size: %d), lru: %d, (lru size: %d), " +                        " purge: %d, (purge size: %d))", ret, itable_size, +                        active_count, table->active_size, lru_count, +                        table->lru_size, purge_count, table->purge_size); +        return ret; +} + +void +inode_table_destroy_all (glusterfs_ctx_t *ctx) { + +        glusterfs_graph_t *trav_graph  = NULL, *tmp = NULL; +        xlator_t          *tree        = NULL; +        inode_table_t     *inode_table = NULL; + +        if (ctx == NULL) +                goto out; + +        /* TODO: Traverse ctx->graphs with in ctx->lock and also the other +         * graph additions and traversals in ctx->lock. +         */ +        list_for_each_entry_safe (trav_graph, tmp, &ctx->graphs, list) { +                tree = trav_graph->first; +                inode_table = tree->itable; +                tree->itable = NULL; +                if (inode_table) +                        inode_table_destroy (inode_table); +        } + out: +        return; +} + +void +inode_table_destroy (inode_table_t *inode_table) { + +        xlator_t *this = NULL; +        inode_t  *tmp = NULL, *trav = NULL; + +        this = THIS; + +        if (inode_table == NULL) +                return; + +        /* Ideally at this point in time, there should be no inodes with +         * refs remaining. But there are quite a few chances where the inodes +         * leak. So we can take three approaches for cleaning up the inode table: +         * 1. Assume there are no leaks and then send a forget on all the inodes +         *    in lru list.(If no leaks there should be no inodes in active list) +         * 2. Knowing there could be leaks and not freeing those inodes will +         *    also not free its inode context and this could leak a lot of +         *    memory, force free the inodes by changeing the ref to 0. +         *    The problem with this is that any refence ti inode after this +         *    calling this funtion will lead to a crash. +         * 3. Knowing there could be leakes, just free the inode contexts of +         *    all the inodes. and let the inodes be alive. This way the major +         *    memory consumed by the inode contexts are freed, but there can +         *    be errors when any inode contexts are accessed after destroying +         *    this table. +         * +         * Not sure which is the approach to be taken, going by approach 2. +         */ + +        /* Approach 3: +         * ret = inode_table_ctx_free (inode_table); +         */ +        pthread_mutex_lock (&inode_table->lock); +        { +                list_for_each_entry_safe (trav, tmp, &inode_table->active, list) { +                        __inode_ref_reduce_by_n (trav, 0); +                } + +                list_for_each_entry_safe (trav, tmp, &inode_table->lru, list) { +                        __inode_forget (trav, 0); +                } +        } +        pthread_mutex_unlock (&inode_table->lock); + +        inode_table_prune (inode_table); + +        GF_FREE (inode_table->inode_hash); +        GF_FREE (inode_table->name_hash); +        if (inode_table->dentry_pool) +                mem_pool_destroy (inode_table->dentry_pool); +        if (inode_table->inode_pool) +                mem_pool_destroy (inode_table->inode_pool); +        if (inode_table->fd_mem_pool) +                mem_pool_destroy (inode_table->fd_mem_pool); + +        pthread_mutex_destroy (&inode_table->lock); + +        GF_FREE (inode_table->name); +        GF_FREE (inode_table); + +        return; +}  inode_t *  inode_from_path (inode_table_t *itable, const char *path) @@ -1535,7 +1755,7 @@ __inode_ctx_set2 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p,          int index = 0;          int set_idx = -1; -        if (!inode || !xlator) +        if (!inode || !xlator || !inode->_ctx)                  return -1;          for (index = 0; index < inode->table->ctxcount; index++) { @@ -1637,7 +1857,7 @@ __inode_ctx_get2 (inode_t *inode, xlator_t *xlator, uint64_t *value1,          int index = 0;          int ret = -1; -        if (!inode || !xlator) +        if (!inode || !xlator || !inode->_ctx)                  goto out;          for (index = 0; index < inode->table->ctxcount; index++) { @@ -1756,6 +1976,9 @@ inode_ctx_del2 (inode_t *inode, xlator_t *xlator, uint64_t *value1,          LOCK (&inode->lock);          { +                if (!inode->_ctx) +                        goto unlock; +                  for (index = 0; index < inode->table->ctxcount;                       index++) {                          if (inode->_ctx[index].xl_key == xlator) @@ -1773,6 +1996,7 @@ inode_ctx_del2 (inode_t *inode, xlator_t *xlator, uint64_t *value1,                          *value2 = inode->_ctx[index].value2;                  inode->_ctx[index].key    = 0; +                inode->_ctx[index].xl_key = NULL;                  inode->_ctx[index].value1 = 0;                  inode->_ctx[index].value2 = 0;          } diff --git a/libglusterfs/src/inode.h b/libglusterfs/src/inode.h index 5d373fcaec9..5c550bc648b 100644 --- a/libglusterfs/src/inode.h +++ b/libglusterfs/src/inode.h @@ -109,6 +109,12 @@ struct _inode {  inode_table_t *  inode_table_new (size_t lru_limit, xlator_t *xl); +void +inode_table_destroy_all (glusterfs_ctx_t *ctx); + +void +inode_table_destroy (inode_table_t *inode_table); +  inode_t *  inode_new (inode_table_t *table); @@ -135,6 +141,9 @@ int  inode_forget (inode_t *inode, uint64_t nlookup);  int +inode_ref_reduce_by_n (inode_t *inode, uint64_t nref); + +int  inode_invalidate(inode_t *inode);  int  | 
