summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'libglusterfs/src/inode.c')
-rw-r--r--libglusterfs/src/inode.c1776
1 files changed, 1242 insertions, 534 deletions
diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c
index ff65d101e..15e0ccf78 100644
--- a/libglusterfs/src/inode.c
+++ b/libglusterfs/src/inode.c
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2007-2009 Z RESEARCH, Inc. <http://www.zresearch.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#ifndef _CONFIG_H
@@ -23,6 +14,7 @@
#endif
#include "inode.h"
+#include "fd.h"
#include "common-utils.h"
#include "statedump.h"
#include <pthread.h>
@@ -32,21 +24,21 @@
#include <time.h>
#include <assert.h>
-/* TODO:
+/* TODO:
move latest accessed dentry to list_head of inode
*/
-#define INODE_DUMP_LIST(head, key_buf, key_prefix, list_type) \
-{ \
- int i = 1;\
- inode_t *inode = NULL;\
- list_for_each_entry (inode, head, list) {\
- gf_proc_dump_build_key(key_buf, key_prefix, "%s.%d",list_type,\
- i++);\
- gf_proc_dump_add_section(key_buf);\
- inode_dump(inode, key);\
- }\
-}
+#define INODE_DUMP_LIST(head, key_buf, key_prefix, list_type) \
+ { \
+ int i = 1; \
+ inode_t *inode = NULL; \
+ list_for_each_entry (inode, head, list) { \
+ gf_proc_dump_build_key(key_buf, key_prefix, \
+ "%s.%d",list_type, i++); \
+ gf_proc_dump_add_section(key_buf); \
+ inode_dump(inode, key); \
+ } \
+ }
static inode_t *
__inode_unref (inode_t *inode);
@@ -54,10 +46,11 @@ __inode_unref (inode_t *inode);
static int
inode_table_prune (inode_table_t *table);
+void
+fd_dump (struct list_head *head, char *prefix);
+
static int
-hash_name (ino_t par,
- const char *name,
- int mod)
+hash_dentry (inode_t *parent, const char *name, int mod)
{
int hash = 0;
int ret = 0;
@@ -68,21 +61,20 @@ hash_name (ino_t par,
hash = (hash << 5) - hash + *name;
}
}
- ret = (hash + par) % mod;
+ ret = (hash + (unsigned long)parent) % mod;
return ret;
}
static int
-hash_inode (ino_t ino,
- int mod)
+hash_gfid (uuid_t uuid, int mod)
{
- int hash = 0;
+ int ret = 0;
- hash = ino % mod;
+ ret = uuid[15] + (uuid[14] << 8);
- return hash;
+ return ret;
}
@@ -92,21 +84,28 @@ __dentry_hash (dentry_t *dentry)
inode_table_t *table = NULL;
int hash = 0;
+ if (!dentry) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "dentry not found");
+ return;
+ }
+
table = dentry->inode->table;
- hash = hash_name (dentry->parent->ino, dentry->name,
- table->hashsize);
+ hash = hash_dentry (dentry->parent, dentry->name,
+ table->hashsize);
list_del_init (&dentry->hash);
list_add (&dentry->hash, &table->name_hash[hash]);
-
- list_del_init (&dentry->parent_list);
- list_add (&dentry->parent_list, &dentry->parent->child_list);
}
static int
__is_dentry_hashed (dentry_t *dentry)
{
+ if (!dentry) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "dentry not found");
+ return 0;
+ }
+
return !list_empty (&dentry->hash);
}
@@ -114,6 +113,11 @@ __is_dentry_hashed (dentry_t *dentry)
static void
__dentry_unhash (dentry_t *dentry)
{
+ if (!dentry) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "dentry not found");
+ return;
+ }
+
list_del_init (&dentry->hash);
}
@@ -121,120 +125,165 @@ __dentry_unhash (dentry_t *dentry)
static void
__dentry_unset (dentry_t *dentry)
{
+ if (!dentry) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "dentry not found");
+ return;
+ }
+
__dentry_unhash (dentry);
list_del_init (&dentry->inode_list);
- if (dentry->name)
- FREE (dentry->name);
+ GF_FREE (dentry->name);
if (dentry->parent) {
- list_del_init (&dentry->parent_list);
__inode_unref (dentry->parent);
dentry->parent = NULL;
}
- FREE (dentry);
+ mem_put (dentry);
}
-static void
-__inode_unhash (inode_t *inode)
+static int
+__foreach_ancestor_dentry (dentry_t *dentry,
+ int (per_dentry_fn) (dentry_t *dentry,
+ void *data),
+ void *data)
{
- list_del_init (&inode->hash);
-}
+ inode_t *parent = NULL;
+ dentry_t *each = NULL;
+ int ret = 0;
+ if (!dentry) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "dentry not found");
+ return 0;
+ }
-static int
-__is_inode_hashed (inode_t *inode)
-{
- return !list_empty (&inode->hash);
+ ret = per_dentry_fn (dentry, data);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_WARNING, "per dentry fn returned %d", ret);
+ goto out;
+ }
+
+ parent = dentry->parent;
+ if (!parent) {
+ gf_log (THIS->name, GF_LOG_WARNING, "parent not found");
+ goto out;
+ }
+
+ list_for_each_entry (each, &parent->dentry_list, inode_list) {
+ ret = __foreach_ancestor_dentry (each, per_dentry_fn, data);
+ if (ret)
+ goto out;
+ }
+out:
+ return ret;
}
-static void
-__inode_hash (inode_t *inode)
+static int
+__check_cycle (dentry_t *a_dentry, void *data)
{
- inode_table_t *table = NULL;
- int hash = 0;
+ inode_t *link_inode = NULL;
- table = inode->table;
- hash = hash_inode (inode->ino, table->hashsize);
+ link_inode = data;
- list_del_init (&inode->hash);
- list_add (&inode->hash, &table->inode_hash[hash]);
+ if (a_dentry->parent == link_inode)
+ return 1;
+
+ return 0;
}
-static inode_t *
-__inode_search (inode_table_t *table,
- ino_t ino)
+static int
+__is_dentry_cyclic (dentry_t *dentry)
{
- int hash = 0;
+ int ret = 0;
inode_t *inode = NULL;
- inode_t *tmp = NULL;
+ char *name = "<nul>";
- hash = hash_inode (ino, table->hashsize);
+ ret = __foreach_ancestor_dentry (dentry, __check_cycle,
+ dentry->inode);
+ if (ret) {
+ inode = dentry->inode;
- list_for_each_entry (tmp, &table->inode_hash[hash], hash) {
- if (tmp->ino == ino) {
- inode = tmp;
- break;
- }
+ if (dentry->name)
+ name = dentry->name;
+
+ gf_log (dentry->inode->table->name, GF_LOG_CRITICAL,
+ "detected cyclic loop formation during inode linkage."
+ " inode (%s) linking under itself as %s",
+ uuid_utoa (inode->gfid), name);
}
- return inode;
+ return ret;
}
-static dentry_t *
-__dentry_search_for_inode (inode_t *inode,
- ino_t par,
- const char *name)
+static void
+__inode_unhash (inode_t *inode)
{
- dentry_t *dentry = NULL;
- dentry_t *tmp = NULL;
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
+ return;
+ }
- list_for_each_entry (tmp, &inode->dentry_list, inode_list) {
- if (tmp->parent->ino == par && !strcmp (tmp->name, name)) {
- dentry = tmp;
- break;
- }
+ list_del_init (&inode->hash);
+}
+
+
+static int
+__is_inode_hashed (inode_t *inode)
+{
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
+ return 0;
}
- return dentry;
+ return !list_empty (&inode->hash);
}
-dentry_t *
-dentry_search_for_inode (inode_t *inode,
- ino_t par,
- const char *name)
+static void
+__inode_hash (inode_t *inode)
{
- dentry_t *dentry = NULL;
- pthread_mutex_lock (&inode->table->lock);
- {
- dentry = __dentry_search_for_inode (inode, par, name);
+ inode_table_t *table = NULL;
+ int hash = 0;
+
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
+ return;
}
- pthread_mutex_unlock (&inode->table->lock);
-
- return dentry;
+
+ table = inode->table;
+ hash = hash_gfid (inode->gfid, 65536);
+
+ list_del_init (&inode->hash);
+ list_add (&inode->hash, &table->inode_hash[hash]);
}
static dentry_t *
-__dentry_search (inode_table_t *table,
- ino_t par,
- const char *name)
+__dentry_search_for_inode (inode_t *inode, uuid_t pargfid, const char *name)
{
- int hash = 0;
dentry_t *dentry = NULL;
dentry_t *tmp = NULL;
- hash = hash_name (par, name, table->hashsize);
+ if (!inode || !name) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode || name not found");
+ return NULL;
+ }
- list_for_each_entry (tmp, &table->name_hash[hash], hash) {
- if (tmp->parent->ino == par && !strcmp (tmp->name, name)) {
+ /* earlier, just the ino was sent, which could have been 0, now
+ we deal with gfid, and if sent gfid is null or 0, no need to
+ continue with the check */
+ if (!pargfid || uuid_is_null (pargfid))
+ return NULL;
+
+ list_for_each_entry (tmp, &inode->dentry_list, inode_list) {
+ if ((uuid_compare (tmp->parent->gfid, pargfid) == 0) &&
+ !strcmp (tmp->name, name)) {
dentry = tmp;
break;
}
@@ -247,31 +296,45 @@ __dentry_search (inode_table_t *table,
static void
__inode_destroy (inode_t *inode)
{
- int index = 0;
+ int index = 0;
xlator_t *xl = NULL;
+ xlator_t *old_THIS = NULL;
- if (!inode->_ctx)
- goto noctx;
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
+ return;
+ }
+
+ if (!inode->_ctx) {
+ gf_log (THIS->name, GF_LOG_WARNING, "_ctx not found");
+ goto noctx;
+ }
- for (index = 0; index < inode->table->xl->ctx->xl_count; index++) {
- if (inode->_ctx[index].key) {
- xl = (xlator_t *)(long)inode->_ctx[index].key;
- if (xl->cbks->forget)
- xl->cbks->forget (xl, inode);
- }
- }
+ for (index = 0; index < inode->table->ctxcount; index++) {
+ if (inode->_ctx[index].xl_key) {
+ xl = (xlator_t *)(long)inode->_ctx[index].xl_key;
+ old_THIS = THIS;
+ THIS = xl;
+ if (xl->cbks->forget)
+ xl->cbks->forget (xl, inode);
+ THIS = old_THIS;
+ }
+ }
- FREE (inode->_ctx);
+ GF_FREE (inode->_ctx);
noctx:
LOCK_DESTROY (&inode->lock);
// memset (inode, 0xb, sizeof (*inode));
- FREE (inode);
+ mem_put (inode);
}
static void
__inode_activate (inode_t *inode)
{
+ if (!inode)
+ return;
+
list_move (&inode->list, &inode->table->active);
inode->table->active_size++;
}
@@ -282,9 +345,11 @@ __inode_passivate (inode_t *inode)
{
dentry_t *dentry = NULL;
dentry_t *t = NULL;
- inode_table_t *table = NULL;
- table = inode->table;
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
+ return;
+ }
list_move_tail (&inode->list, &inode->table->lru);
inode->table->lru_size++;
@@ -301,15 +366,16 @@ __inode_retire (inode_t *inode)
{
dentry_t *dentry = NULL;
dentry_t *t = NULL;
- inode_table_t *table = NULL;
- table = inode->table;
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
+ return;
+ }
list_move_tail (&inode->list, &inode->table->purge);
inode->table->purge_size++;
__inode_unhash (inode);
- assert (list_empty (&inode->child_list));
list_for_each_entry_safe (dentry, t, &inode->dentry_list, inode_list) {
__dentry_unset (dentry);
@@ -320,17 +386,20 @@ __inode_retire (inode_t *inode)
static inode_t *
__inode_unref (inode_t *inode)
{
- if (inode->ino == 1)
+ if (!inode)
+ return NULL;
+
+ if (__is_root_gfid(inode->gfid))
return inode;
- assert (inode->ref);
+ GF_ASSERT (inode->ref);
--inode->ref;
if (!inode->ref) {
inode->table->active_size--;
- if (inode->nlookup && __is_inode_hashed (inode))
+ if (inode->nlookup)
__inode_passivate (inode);
else
__inode_retire (inode);
@@ -343,6 +412,9 @@ __inode_unref (inode_t *inode)
static inode_t *
__inode_ref (inode_t *inode)
{
+ if (!inode)
+ return NULL;
+
if (!inode->ref) {
inode->table->lru_size--;
__inode_activate (inode);
@@ -358,6 +430,9 @@ inode_unref (inode_t *inode)
{
inode_table_t *table = NULL;
+ if (!inode)
+ return NULL;
+
table = inode->table;
pthread_mutex_lock (&table->lock);
@@ -377,6 +452,9 @@ inode_ref (inode_t *inode)
{
inode_table_t *table = NULL;
+ if (!inode)
+ return NULL;
+
table = inode->table;
pthread_mutex_lock (&table->lock);
@@ -390,25 +468,38 @@ inode_ref (inode_t *inode)
static dentry_t *
-__dentry_create (inode_t *inode,
- inode_t *parent,
- const char *name)
+__dentry_create (inode_t *inode, inode_t *parent, const char *name)
{
dentry_t *newd = NULL;
- newd = (void *) CALLOC (1, sizeof (*newd));
+ if (!inode || !parent || !name) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING,
+ "inode || parent || name not found");
+ return NULL;
+ }
+
+ newd = mem_get0 (parent->table->dentry_pool);
+ if (newd == NULL) {
+ goto out;
+ }
INIT_LIST_HEAD (&newd->inode_list);
- INIT_LIST_HEAD (&newd->parent_list);
INIT_LIST_HEAD (&newd->hash);
- list_add (&newd->parent_list, &parent->child_list);
- newd->parent = __inode_ref (parent);
- newd->name = strdup (name);
+ newd->name = gf_strdup (name);
+ if (newd->name == NULL) {
+ mem_put (newd);
+ newd = NULL;
+ goto out;
+ }
+
+ if (parent)
+ newd->parent = __inode_ref (parent);
list_add (&newd->inode_list, &inode->dentry_list);
newd->inode = inode;
+out:
return newd;
}
@@ -418,9 +509,15 @@ __inode_create (inode_table_t *table)
{
inode_t *newi = NULL;
- newi = (void *) CALLOC (1, sizeof (*newi));
- if (!newi)
+ if (!table) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "table not found");
return NULL;
+ }
+
+ newi = mem_get0 (table->inode_pool);
+ if (!newi) {
+ goto out;
+ }
newi->table = table;
@@ -430,14 +527,21 @@ __inode_create (inode_table_t *table)
INIT_LIST_HEAD (&newi->list);
INIT_LIST_HEAD (&newi->hash);
INIT_LIST_HEAD (&newi->dentry_list);
- INIT_LIST_HEAD (&newi->child_list);
+ newi->_ctx = GF_CALLOC (1,
+ (sizeof (struct _inode_ctx) * table->ctxcount),
+ gf_common_mt_inode_ctx);
+ if (newi->_ctx == NULL) {
+ LOCK_DESTROY (&newi->lock);
+ mem_put (newi);
+ newi = NULL;
+ goto out;
+ }
list_add (&newi->list, &table->lru);
table->lru_size++;
- newi->_ctx = CALLOC (1, (sizeof (struct _inode_ctx) *
- table->xl->ctx->xl_count));
+out:
return newi;
}
@@ -448,10 +552,17 @@ inode_new (inode_table_t *table)
{
inode_t *inode = NULL;
+ if (!table) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
+ return NULL;
+ }
+
pthread_mutex_lock (&table->lock);
{
inode = __inode_create (table);
- __inode_ref (inode);
+ if (inode != NULL) {
+ __inode_ref (inode);
+ }
}
pthread_mutex_unlock (&table->lock);
@@ -462,6 +573,9 @@ inode_new (inode_table_t *table)
static inode_t *
__inode_lookup (inode_t *inode)
{
+ if (!inode)
+ return NULL;
+
inode->nlookup++;
return inode;
@@ -471,7 +585,10 @@ __inode_lookup (inode_t *inode)
static inode_t *
__inode_forget (inode_t *inode, uint64_t nlookup)
{
- assert (inode->nlookup >= nlookup);
+ if (!inode)
+ return NULL;
+
+ GF_ASSERT (inode->nlookup >= nlookup);
inode->nlookup -= nlookup;
@@ -482,25 +599,48 @@ __inode_forget (inode_t *inode, uint64_t nlookup)
}
-inode_t *
-inode_search (inode_table_t *table,
- ino_t ino,
- const char *name)
+dentry_t *
+__dentry_grep (inode_table_t *table, inode_t *parent, const char *name)
{
- inode_t *inode = NULL;
+ int hash = 0;
dentry_t *dentry = NULL;
+ dentry_t *tmp = NULL;
+
+ if (!table || !name || !parent)
+ return NULL;
+
+ hash = hash_dentry (parent, name, table->hashsize);
+
+ list_for_each_entry (tmp, &table->name_hash[hash], hash) {
+ if (tmp->parent == parent && !strcmp (tmp->name, name)) {
+ dentry = tmp;
+ break;
+ }
+ }
+
+ return dentry;
+}
+
+
+inode_t *
+inode_grep (inode_table_t *table, inode_t *parent, const char *name)
+{
+ inode_t *inode = NULL;
+ dentry_t *dentry = NULL;
+
+ if (!table || !parent || !name) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING,
+ "table || parent || name not found");
+ return NULL;
+ }
pthread_mutex_lock (&table->lock);
{
- if (!name) {
- inode = __inode_search (table, ino);
- } else {
- dentry = __dentry_search (table, ino, name);
-
- if (dentry)
- inode = dentry->inode;
- }
-
+ dentry = __dentry_grep (table, parent, name);
+
+ if (dentry)
+ inode = dentry->inode;
+
if (inode)
__inode_ref (inode);
}
@@ -510,138 +650,255 @@ inode_search (inode_table_t *table,
}
-static void
-__copy_dentries (inode_t *oldi, inode_t *newi)
+inode_t *
+inode_resolve (inode_table_t *table, char *path)
{
- dentry_t *dentry = NULL;
- dentry_t *newd = NULL;
- dentry_t *tmp = NULL;
+ char *tmp = NULL, *bname = NULL, *str = NULL, *saveptr = NULL;
+ inode_t *inode = NULL, *parent = NULL;
- list_for_each_entry (dentry, &oldi->dentry_list, inode_list) {
- tmp = __dentry_search_for_inode (newi, dentry->parent->ino,
- dentry->name);
+ if ((path == NULL) || (table == NULL)) {
+ goto out;
+ }
- if (!tmp) {
- newd = __dentry_create (newi, dentry->parent,
- dentry->name);
- } else {
- newd = tmp;
+ parent = inode_ref (table->root);
+ str = tmp = gf_strdup (path);
+
+ while (1) {
+ bname = strtok_r (str, "/", &saveptr);
+ if (bname == NULL) {
+ break;
}
- if (__is_dentry_hashed (dentry)) {
- __dentry_unhash (dentry);
- __dentry_hash (newd);
+ if (inode != NULL) {
+ inode_unref (inode);
}
+
+ inode = inode_grep (table, parent, bname);
+ if (inode == NULL) {
+ break;
+ }
+
+ if (parent != NULL) {
+ inode_unref (parent);
+ }
+
+ parent = inode_ref (inode);
+ str = NULL;
}
+
+ inode_unref (parent);
+ GF_FREE (tmp);
+out:
+ return inode;
}
-static void
-__adopt_children (inode_t *oldi, inode_t *newi)
+int
+inode_grep_for_gfid (inode_table_t *table, inode_t *parent, const char *name,
+ uuid_t gfid, ia_type_t *type)
{
- dentry_t *dentry = NULL;
+ inode_t *inode = NULL;
+ dentry_t *dentry = NULL;
+ int ret = -1;
+
+ if (!table || !parent || !name) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING,
+ "table || parent || name not found");
+ return ret;
+ }
- list_for_each_entry (dentry, &oldi->child_list, parent_list) {
- assert (dentry->parent == oldi);
- __inode_unref (dentry->parent);
- dentry->parent = __inode_ref (newi);
+ pthread_mutex_lock (&table->lock);
+ {
+ dentry = __dentry_grep (table, parent, name);
+
+ if (dentry)
+ inode = dentry->inode;
+
+ if (inode) {
+ uuid_copy (gfid, inode->gfid);
+ *type = inode->ia_type;
+ ret = 0;
+ }
}
+ pthread_mutex_unlock (&table->lock);
- list_splice_init (&oldi->child_list, &newi->child_list);
+ return ret;
}
-static void
-__inode_replace (inode_t *oldi, inode_t *newi)
+/* return 1 if gfid is of root, 0 if not */
+gf_boolean_t
+__is_root_gfid (uuid_t gfid)
{
- gf_log (oldi->table->name, GF_LOG_DEBUG,
- "inode(%"PRId64") replaced (%"PRId64"",
- oldi->ino, newi->ino);
+ uuid_t root;
+
+ memset (root, 0, 16);
+ root[15] = 1;
- __copy_dentries (oldi, newi);
- __adopt_children (oldi, newi);
+ if (uuid_compare (gfid, root) == 0)
+ return _gf_true;
- newi->nlookup = oldi->nlookup;
- newi->generation = oldi->generation;
+ return _gf_false;
+}
+
+
+inode_t *
+__inode_find (inode_table_t *table, uuid_t gfid)
+{
+ inode_t *inode = NULL;
+ inode_t *tmp = NULL;
+ int hash = 0;
+
+ if (!table) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "table not found");
+ goto out;
+ }
+
+ if (__is_root_gfid (gfid))
+ return table->root;
+
+ hash = hash_gfid (gfid, 65536);
+
+ list_for_each_entry (tmp, &table->inode_hash[hash], hash) {
+ if (uuid_compare (tmp->gfid, gfid) == 0) {
+ inode = tmp;
+ break;
+ }
+ }
+
+out:
+ return inode;
+}
+
+
+inode_t *
+inode_find (inode_table_t *table, uuid_t gfid)
+{
+ inode_t *inode = NULL;
- oldi->nlookup = 0;
- oldi->generation = 0;
+ if (!table) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "table not found");
+ return NULL;
+ }
- __inode_unhash (oldi);
+ pthread_mutex_lock (&table->lock);
+ {
+ inode = __inode_find (table, gfid);
+ if (inode)
+ __inode_ref (inode);
+ }
+ pthread_mutex_unlock (&table->lock);
- if (newi->ino == 1)
- newi->table->root = newi;
+ return inode;
}
static inode_t *
-__inode_link (inode_t *inode,
- inode_t *parent,
- const char *name,
- struct stat *stbuf)
+__inode_link (inode_t *inode, inode_t *parent, const char *name,
+ struct iatt *iatt)
{
dentry_t *dentry = NULL;
dentry_t *old_dentry = NULL;
inode_t *old_inode = NULL;
inode_table_t *table = NULL;
+ inode_t *link_inode = NULL;
+
+ if (!inode)
+ return NULL;
table = inode->table;
+ if (!table)
+ return NULL;
+
+ if (parent) {
+ /* We should prevent inode linking between different
+ inode tables. This can cause errors which is very
+ hard to catch/debug. */
+ if (inode->table != parent->table) {
+ GF_ASSERT (!"link attempted b/w inodes of diff table");
+ }
+ }
+
+ link_inode = inode;
- if (inode->ino)
- assert (inode->ino == stbuf->st_ino);
+ if (!__is_inode_hashed (inode)) {
+ if (!iatt)
+ return NULL;
- inode->ino = stbuf->st_ino;
- inode->st_mode = stbuf->st_mode;
+ if (uuid_is_null (iatt->ia_gfid))
+ return NULL;
- old_inode = __inode_search (table, stbuf->st_ino);
+ old_inode = __inode_find (table, iatt->ia_gfid);
- if (old_inode && old_inode != inode) {
- __inode_ref (old_inode);
- __inode_replace (old_inode, inode);
- __inode_unref (old_inode);
+ if (old_inode) {
+ link_inode = old_inode;
+ } else {
+ uuid_copy (inode->gfid, iatt->ia_gfid);
+ inode->ia_type = iatt->ia_type;
+ __inode_hash (inode);
+ }
}
- __inode_hash (inode);
+ if (name) {
+ if (!strcmp(name, ".") || !strcmp(name, ".."))
+ return link_inode;
+ }
+
+ /* use only link_inode beyond this point */
if (parent) {
- dentry = __dentry_search_for_inode (inode, parent->ino, name);
- if (!dentry) {
- dentry = __dentry_create (inode, parent, name);
- }
+ old_dentry = __dentry_grep (table, parent, name);
+
+ if (!old_dentry || old_dentry->inode != link_inode) {
+ dentry = __dentry_create (link_inode, parent, name);
+ if (!dentry) {
+ gf_log_callingfn (THIS->name, GF_LOG_ERROR,
+ "dentry create failed on "
+ "inode %s with parent %s",
+ uuid_utoa (link_inode->gfid),
+ uuid_utoa (parent->gfid));
+ return NULL;
+ }
+ if (old_inode && __is_dentry_cyclic (dentry)) {
+ __dentry_unset (dentry);
+ return NULL;
+ }
+ __dentry_hash (dentry);
- old_dentry = __dentry_search (table, parent->ino, name);
- if (old_dentry) {
- __dentry_unhash (old_dentry);
+ if (old_dentry)
+ __dentry_unset (old_dentry);
}
+ }
- __dentry_hash (dentry);
- } else if (inode->ino != 1) {
- gf_log (table->name, GF_LOG_DEBUG,
- "child (%"PRId64") without a parent!", inode->ino);
- }
-
- return inode;
+ return link_inode;
}
-int
-inode_link (inode_t *inode,
- inode_t *parent,
- const char *name,
- struct stat *stbuf)
+inode_t *
+inode_link (inode_t *inode, inode_t *parent, const char *name,
+ struct iatt *iatt)
{
inode_table_t *table = NULL;
+ inode_t *linked_inode = NULL;
+
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
+ return NULL;
+ }
table = inode->table;
pthread_mutex_lock (&table->lock);
{
- inode = __inode_link (inode, parent, name, stbuf);
+ linked_inode = __inode_link (inode, parent, name, iatt);
+
+ if (linked_inode)
+ __inode_ref (linked_inode);
}
pthread_mutex_unlock (&table->lock);
inode_table_prune (table);
- return 0;
+ return linked_inode;
}
@@ -649,20 +906,17 @@ int
inode_lookup (inode_t *inode)
{
inode_table_t *table = NULL;
- inode_t *lookup_inode = NULL;
+
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
+ return -1;
+ }
table = inode->table;
- lookup_inode = inode;
pthread_mutex_lock (&table->lock);
{
- if (!__is_inode_hashed (inode)) {
- lookup_inode = __inode_search (table, inode->ino);
- if (lookup_inode == NULL)
- lookup_inode = inode;
- }
-
- __inode_lookup (lookup_inode);
+ __inode_lookup (inode);
}
pthread_mutex_unlock (&table->lock);
@@ -674,20 +928,17 @@ int
inode_forget (inode_t *inode, uint64_t nlookup)
{
inode_table_t *table = NULL;
- inode_t *forget_inode = NULL;
+
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
+ return -1;
+ }
table = inode->table;
- forget_inode = inode;
pthread_mutex_lock (&table->lock);
{
- if (!__is_inode_hashed (inode)) {
- forget_inode = __inode_search (table, inode->ino);
- if (forget_inode == NULL)
- forget_inode = inode;
- }
-
- __inode_forget (forget_inode, nlookup);
+ __inode_forget (inode, nlookup);
}
pthread_mutex_unlock (&table->lock);
@@ -696,42 +947,86 @@ inode_forget (inode_t *inode, uint64_t nlookup)
return 0;
}
+/*
+ * Invalidate an inode. This is invoked when a translator decides that an inode's
+ * cache is no longer valid. Any translator interested in taking action in this
+ * situation can define the invalidate callback.
+ */
+int
+inode_invalidate(inode_t *inode)
+{
+ int ret = 0;
+ xlator_t *xl = NULL;
+ xlator_t *old_THIS = NULL;
+
+ if (!inode) {
+ gf_log_callingfn(THIS->name, GF_LOG_WARNING, "inode not found");
+ return -1;
+ }
+
+ /*
+ * The master xlator is not in the graph but it can define an invalidate
+ * handler.
+ */
+ xl = inode->table->xl->ctx->master;
+ if (xl && xl->cbks->invalidate) {
+ old_THIS = THIS;
+ THIS = xl;
+ ret = xl->cbks->invalidate(xl, inode);
+ THIS = old_THIS;
+ if (ret)
+ return ret;
+ }
+
+ xl = inode->table->xl->graph->first;
+ while (xl) {
+ old_THIS = THIS;
+ THIS = xl;
+ if (xl->cbks->invalidate)
+ ret = xl->cbks->invalidate(xl, inode);
+ THIS = old_THIS;
+
+ if (ret)
+ break;
+
+ xl = xl->next;
+ }
+
+ return ret;
+}
+
static void
-__inode_unlink (inode_t *inode,
- inode_t *parent,
- const char *name)
+__inode_unlink (inode_t *inode, inode_t *parent, const char *name)
{
dentry_t *dentry = NULL;
- dentry = __dentry_search_for_inode (inode, parent->ino, name);
+ if (!inode || !parent || !name)
+ return;
+
+ dentry = __dentry_search_for_inode (inode, parent->gfid, name);
- /* dentry NULL for corrupted backend */
- if (dentry)
- __dentry_unset (dentry);
+ /* dentry NULL for corrupted backend */
+ if (dentry)
+ __dentry_unset (dentry);
}
-
+
void
-inode_unlink (inode_t *inode,
- inode_t *parent,
- const char *name)
+inode_unlink (inode_t *inode, inode_t *parent, const char *name)
{
inode_table_t *table = NULL;
- inode_t *unlink_inode = NULL;
+
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
+ return;
+ }
table = inode->table;
- unlink_inode = inode;
pthread_mutex_lock (&table->lock);
{
- if (!__is_inode_hashed (inode)) {
- unlink_inode = __inode_search (table, inode->ino);
- if (unlink_inode == NULL)
- unlink_inode = inode;
- }
-
- __inode_unlink (unlink_inode, parent, name);
+ __inode_unlink (inode, parent, name);
}
pthread_mutex_unlock (&table->lock);
@@ -740,33 +1035,21 @@ inode_unlink (inode_t *inode,
int
-inode_rename (inode_table_t *table,
- inode_t *srcdir,
- const char *srcname,
- inode_t *dstdir,
- const char *dstname,
- inode_t *inode,
- struct stat *stbuf)
+inode_rename (inode_table_t *table, inode_t *srcdir, const char *srcname,
+ inode_t *dstdir, const char *dstname, inode_t *inode,
+ struct iatt *iatt)
{
- dentry_t *old_dst = NULL;
- inode_t *rename_inode = NULL;
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
+ return -1;
+ }
- rename_inode = inode;
+ table = inode->table;
pthread_mutex_lock (&table->lock);
{
- if (!__is_inode_hashed (inode)) {
- rename_inode = __inode_search (table, inode->ino);
- if (rename_inode == NULL)
- rename_inode = inode;
- }
-
- old_dst = __dentry_search (table, dstdir->ino, dstname);
- if (old_dst)
- __dentry_unset (old_dst);
-
- __inode_unlink (rename_inode, srcdir, srcname);
- __inode_link (rename_inode, dstdir, dstname, stbuf);
+ __inode_link (inode, dstdir, dstname, iatt);
+ __inode_unlink (inode, srcdir, srcname);
}
pthread_mutex_unlock (&table->lock);
@@ -779,46 +1062,57 @@ inode_rename (inode_table_t *table,
static dentry_t *
__dentry_search_arbit (inode_t *inode)
{
- dentry_t *dentry = NULL;
- dentry_t *trav = NULL;
+ dentry_t *dentry = NULL;
+ dentry_t *trav = NULL;
- list_for_each_entry (trav, &inode->dentry_list, inode_list) {
- if (__is_dentry_hashed (trav)) {
- dentry = trav;
- break;
- }
- }
+ if (!inode)
+ return NULL;
- if (!dentry) {
- list_for_each_entry (trav, &inode->dentry_list, inode_list) {
- dentry = trav;
- break;
- }
- }
+ list_for_each_entry (trav, &inode->dentry_list, inode_list) {
+ if (__is_dentry_hashed (trav)) {
+ dentry = trav;
+ break;
+ }
+ }
- return dentry;
+ if (!dentry) {
+ list_for_each_entry (trav, &inode->dentry_list, inode_list) {
+ dentry = trav;
+ break;
+ }
+ }
+
+ return dentry;
}
inode_t *
-inode_parent (inode_t *inode, ino_t par, const char *name)
+inode_parent (inode_t *inode, uuid_t pargfid, const char *name)
{
inode_t *parent = NULL;
inode_table_t *table = NULL;
dentry_t *dentry = NULL;
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
+ return NULL;
+ }
+
table = inode->table;
pthread_mutex_lock (&table->lock);
{
- if (par && name) {
- dentry = __dentry_search_for_inode (inode, par, name);
+ if (pargfid && !uuid_is_null (pargfid) && name) {
+ dentry = __dentry_search_for_inode (inode, pargfid, name);
} else {
dentry = __dentry_search_arbit (inode);
}
if (dentry)
- parent = __inode_ref (dentry->parent);
+ parent = dentry->parent;
+
+ if (parent)
+ __inode_ref (parent);
}
pthread_mutex_unlock (&table->lock);
@@ -826,108 +1120,136 @@ inode_parent (inode_t *inode, ino_t par, const char *name)
}
-int32_t
-inode_path (inode_t *inode,
- const char *name,
- char **bufp)
+int
+__inode_path (inode_t *inode, const char *name, char **bufp)
{
inode_table_t *table = NULL;
- dentry_t *trav = NULL;
- size_t i = 0, size = 0;
- int64_t ret = 0;
- int len = 0;
- char *buf = NULL;
-
+ inode_t *itrav = NULL;
+ dentry_t *trav = NULL;
+ size_t i = 0, size = 0;
+ int64_t ret = 0;
+ int len = 0;
+ char *buf = NULL;
+
+ if (!inode || uuid_is_null (inode->gfid)) {
+ GF_ASSERT (0);
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "invalid inode");
+ return -1;
+ }
+
table = inode->table;
- pthread_mutex_lock (&table->lock);
- {
- for (trav = __dentry_search_arbit (inode); trav;
- trav = __dentry_search_arbit (trav->parent)) {
- i ++; /* "/" */
- i += strlen (trav->name);
- if (i > PATH_MAX) {
- gf_log ("inode", GF_LOG_CRITICAL,
- "possible infinite loop detected, "
- "forcing break. name=(%s)", name);
- ret = -ENOENT;
- goto unlock;
- }
+ itrav = inode;
+ for (trav = __dentry_search_arbit (itrav); trav;
+ trav = __dentry_search_arbit (itrav)) {
+ itrav = trav->parent;
+ i ++; /* "/" */
+ i += strlen (trav->name);
+ if (i > PATH_MAX) {
+ gf_log (table->name, GF_LOG_CRITICAL,
+ "possible infinite loop detected, "
+ "forcing break. name=(%s)", name);
+ ret = -ENOENT;
+ goto out;
}
-
- if ((inode->ino != 1) &&
- (i == 0)) {
- gf_log (table->name, GF_LOG_DEBUG,
- "no dentry for non-root inode %"PRId64,
- inode->ino);
- ret = -ENOENT;
- goto unlock;
- }
+ }
+
+ if (!__is_root_gfid (itrav->gfid)) {
+ /* "<gfid:00000000-0000-0000-0000-000000000000>"/path */
+ i += GFID_STR_PFX_LEN;
+ }
+
+ if (name) {
+ i++;
+ i += strlen (name);
+ }
+
+ ret = i;
+ size = i + 1;
+ buf = GF_CALLOC (size, sizeof (char), gf_common_mt_char);
+ if (buf) {
+
+ buf[size - 1] = 0;
if (name) {
- i++;
- i += strlen (name);
+ len = strlen (name);
+ strncpy (buf + (i - len), name, len);
+ buf[i-len-1] = '/';
+ i -= (len + 1);
}
- ret = i;
- size = i + 1;
- buf = CALLOC (size, sizeof (char));
- if (buf) {
+ itrav = inode;
+ for (trav = __dentry_search_arbit (itrav); trav;
+ trav = __dentry_search_arbit (itrav)) {
+ itrav = trav->parent;
+ len = strlen (trav->name);
+ strncpy (buf + (i - len), trav->name, len);
+ buf[i-len-1] = '/';
+ i -= (len + 1);
+ }
- buf[size - 1] = 0;
+ if (!__is_root_gfid (itrav->gfid)) {
+ snprintf (&buf[i-GFID_STR_PFX_LEN], GFID_STR_PFX_LEN,
+ INODE_PATH_FMT, uuid_utoa (itrav->gfid));
+ buf[i-1] = '>';
+ }
- if (name) {
- len = strlen (name);
- strncpy (buf + (i - len), name, len);
- buf[i-len-1] = '/';
- i -= (len + 1);
- }
+ *bufp = buf;
+ } else {
+ ret = -ENOMEM;
+ }
- for (trav = __dentry_search_arbit (inode); trav;
- trav = __dentry_search_arbit (trav->parent)) {
- len = strlen (trav->name);
- strncpy (buf + (i - len), trav->name, len);
- buf[i-len-1] = '/';
- i -= (len + 1);
- }
- *bufp = buf;
+out:
+ if (__is_root_gfid (inode->gfid) && !name) {
+ ret = 1;
+ GF_FREE (buf);
+ buf = GF_CALLOC (ret + 1, sizeof (char), gf_common_mt_char);
+ if (buf) {
+ strcpy (buf, "/");
+ *bufp = buf;
} else {
- gf_log (table->name, GF_LOG_ERROR,
- "out of memory");
- ret = -ENOMEM;
- }
+ ret = -ENOMEM;
+ }
}
-unlock:
- pthread_mutex_unlock (&table->lock);
- if (inode->ino == 1 && !name) {
- ret = 1;
- if (buf) {
- FREE (buf);
- }
- buf = CALLOC (ret + 1, sizeof (char));
- if (buf) {
- strcpy (buf, "/");
- *bufp = buf;
- } else {
- gf_log (table->name, GF_LOG_ERROR,
- "out of memory");
- ret = -ENOMEM;
- }
- }
+ if (ret < 0)
+ *bufp = NULL;
+ return ret;
+}
+
+
+int
+inode_path (inode_t *inode, const char *name, char **bufp)
+{
+ inode_table_t *table = NULL;
+ int ret = -1;
+
+ if (!inode)
+ return -1;
+
+ table = inode->table;
+
+ pthread_mutex_lock (&table->lock);
+ {
+ ret = __inode_path (inode, name, bufp);
+ }
+ pthread_mutex_unlock (&table->lock);
return ret;
}
+
static int
inode_table_prune (inode_table_t *table)
{
int ret = 0;
struct list_head purge = {0, };
- inode_t *del = NULL;
- inode_t *tmp = NULL;
- inode_t *entry = NULL;
+ inode_t *del = NULL;
+ inode_t *tmp = NULL;
+ inode_t *entry = NULL;
+ if (!table)
+ return -1;
INIT_LIST_HEAD (&purge);
@@ -935,7 +1257,7 @@ inode_table_prune (inode_table_t *table)
{
while (table->lru_limit
&& table->lru_size > (table->lru_limit)) {
-
+
entry = list_entry (table->lru.next, inode_t, list);
table->lru_size--;
@@ -945,7 +1267,7 @@ inode_table_prune (inode_table_t *table)
}
list_splice_init (&table->purge, &purge);
- table->purge_size = 0;
+ table->purge_size = 0;
}
pthread_mutex_unlock (&table->lock);
@@ -964,15 +1286,19 @@ inode_table_prune (inode_table_t *table)
static void
__inode_table_init_root (inode_table_t *table)
{
- inode_t *root = NULL;
- struct stat stbuf = {0, };
+ inode_t *root = NULL;
+ struct iatt iatt = {0, };
+
+ if (!table)
+ return;
root = __inode_create (table);
- stbuf.st_ino = 1;
- stbuf.st_mode = S_IFDIR|0755;
+ iatt.ia_gfid[15] = 1;
+ iatt.ia_ino = 1;
+ iatt.ia_type = IA_IFDIR;
- __inode_link (root, NULL, NULL, &stbuf);
+ __inode_link (root, NULL, NULL, &iatt);
table->root = root;
}
@@ -981,40 +1307,59 @@ inode_table_t *
inode_table_new (size_t lru_limit, xlator_t *xl)
{
inode_table_t *new = NULL;
- int ret = 0;
+ int ret = -1;
int i = 0;
- new = (void *)calloc (1, sizeof (*new));
+ new = (void *)GF_CALLOC(1, sizeof (*new), gf_common_mt_inode_table_t);
if (!new)
return NULL;
new->xl = xl;
+ new->ctxcount = xl->graph->xl_count + 1;
new->lru_limit = lru_limit;
new->hashsize = 14057; /* TODO: Random Number?? */
- new->inode_hash = (void *)calloc (new->hashsize,
- sizeof (struct list_head));
- if (!new->inode_hash) {
- FREE (new);
- return NULL;
- }
+ /* In case FUSE is initing the inode table. */
+ if (lru_limit == 0)
+ lru_limit = DEFAULT_INODE_MEMPOOL_ENTRIES;
- new->name_hash = (void *)calloc (new->hashsize,
- sizeof (struct list_head));
- if (!new->name_hash) {
- FREE (new->inode_hash);
- FREE (new);
- return NULL;
- }
+ new->inode_pool = mem_pool_new (inode_t, lru_limit);
- for (i=0; i<new->hashsize; i++) {
+ if (!new->inode_pool)
+ goto out;
+
+ new->dentry_pool = mem_pool_new (dentry_t, lru_limit);
+
+ if (!new->dentry_pool)
+ goto out;
+
+ new->inode_hash = (void *)GF_CALLOC (65536,
+ sizeof (struct list_head),
+ gf_common_mt_list_head);
+ if (!new->inode_hash)
+ goto out;
+
+ new->name_hash = (void *)GF_CALLOC (new->hashsize,
+ sizeof (struct list_head),
+ gf_common_mt_list_head);
+ if (!new->name_hash)
+ goto out;
+
+ /* if number of fd open in one process is more than this,
+ we may hit perf issues */
+ new->fd_mem_pool = mem_pool_new (fd_t, 1024);
+
+ if (!new->fd_mem_pool)
+ goto out;
+
+ for (i = 0; i < 65536; i++) {
INIT_LIST_HEAD (&new->inode_hash[i]);
}
- for (i=0; i<new->hashsize; i++) {
+ for (i = 0; i < new->hashsize; i++) {
INIT_LIST_HEAD (&new->name_hash[i]);
}
@@ -1022,16 +1367,31 @@ inode_table_new (size_t lru_limit, xlator_t *xl)
INIT_LIST_HEAD (&new->lru);
INIT_LIST_HEAD (&new->purge);
- ret = asprintf (&new->name, "%s/inode", xl->name);
+ ret = gf_asprintf (&new->name, "%s/inode", xl->name);
if (-1 == ret) {
/* TODO: This should be ok to continue, check with avati */
;
}
- __inode_table_init_root (new);
+ __inode_table_init_root (new);
pthread_mutex_init (&new->lock, NULL);
+ ret = 0;
+out:
+ if (ret) {
+ if (new) {
+ GF_FREE (new->inode_hash);
+ GF_FREE (new->name_hash);
+ if (new->dentry_pool)
+ mem_pool_destroy (new->dentry_pool);
+ if (new->inode_pool)
+ mem_pool_destroy (new->inode_pool);
+ GF_FREE (new);
+ new = NULL;
+ }
+ }
+
return new;
}
@@ -1039,236 +1399,489 @@ inode_table_new (size_t lru_limit, xlator_t *xl)
inode_t *
inode_from_path (inode_table_t *itable, const char *path)
{
- inode_t *inode = NULL;
- inode_t *parent = NULL;
- inode_t *root = NULL;
- inode_t *curr = NULL;
- char *pathname = NULL;
- char *component = NULL, *next_component = NULL;
- char *strtokptr = NULL;
-
- /* top-down approach */
- root = itable->root;
- parent = inode_ref (root);
- pathname = strdup (path);
- component = strtok_r (pathname, "/", &strtokptr);
-
- if (component == NULL)
- /* root inode */
- inode = inode_ref (parent);
-
- while (component) {
- curr = inode_search (itable, parent->ino, component);
-
- if (curr == NULL) {
- component = strtok_r (NULL, "/", &strtokptr);
- break;
- }
-
- next_component = strtok_r (NULL, "/", &strtokptr);
-
- if (next_component) {
- inode_unref (parent);
- parent = curr;
- curr = NULL;
- } else {
- inode = curr;
- }
-
- component = next_component;
- }
-
- if (parent)
- inode_unref (parent);
+ inode_t *inode = NULL;
+ inode_t *parent = NULL;
+ inode_t *root = NULL;
+ inode_t *curr = NULL;
+ char *pathname = NULL;
+ char *component = NULL, *next_component = NULL;
+ char *strtokptr = NULL;
+
+ if (!itable || !path)
+ return NULL;
- if (pathname)
- free (pathname);
+ /* top-down approach */
+ pathname = gf_strdup (path);
+ if (pathname == NULL) {
+ goto out;
+ }
+
+ root = itable->root;
+ parent = inode_ref (root);
+ component = strtok_r (pathname, "/", &strtokptr);
+
+ if (component == NULL)
+ /* root inode */
+ inode = inode_ref (parent);
+
+ while (component) {
+ curr = inode_grep (itable, parent, component);
+
+ if (curr == NULL) {
+ strtok_r (NULL, "/", &strtokptr);
+ break;
+ }
+
+ next_component = strtok_r (NULL, "/", &strtokptr);
+
+ if (next_component) {
+ inode_unref (parent);
+ parent = curr;
+ curr = NULL;
+ } else {
+ inode = curr;
+ }
+
+ component = next_component;
+ }
+
+ if (parent)
+ inode_unref (parent);
- return inode;
+ GF_FREE (pathname);
+
+out:
+ return inode;
}
+
int
-__inode_ctx_put (inode_t *inode, xlator_t *xlator, uint64_t value)
+__inode_ctx_set2 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p,
+ uint64_t *value2_p)
{
int ret = 0;
int index = 0;
- int put_idx = -1;
+ int set_idx = -1;
+
+ if (!inode || !xlator)
+ return -1;
- for (index = 0; index < xlator->ctx->xl_count; index++) {
- if (!inode->_ctx[index].key) {
- if (put_idx == -1)
- put_idx = index;
+ for (index = 0; index < inode->table->ctxcount; index++) {
+ if (!inode->_ctx[index].xl_key) {
+ if (set_idx == -1)
+ set_idx = index;
/* dont break, to check if key already exists
further on */
}
- if (inode->_ctx[index].key == (uint64_t)(long) xlator) {
- put_idx = index;
+ if (inode->_ctx[index].xl_key == xlator) {
+ set_idx = index;
break;
}
}
-
- if (put_idx == -1) {
+
+ if (set_idx == -1) {
ret = -1;
goto out;;
}
- inode->_ctx[put_idx].key = (uint64_t)(long) xlator;
- inode->_ctx[put_idx].value = value;
+ inode->_ctx[set_idx].xl_key = xlator;
+ if (value1_p)
+ inode->_ctx[set_idx].value1 = *value1_p;
+ if (value2_p)
+ inode->_ctx[set_idx].value2 = *value2_p;
out:
return ret;
}
int
-inode_ctx_put (inode_t *inode, xlator_t *xlator, uint64_t value)
+__inode_ctx_set0 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p)
+{
+ return __inode_ctx_set2 (inode, xlator, value1_p, NULL);
+}
+
+int
+__inode_ctx_set1 (inode_t *inode, xlator_t *xlator, uint64_t *value2_p)
+{
+ return __inode_ctx_set2 (inode, xlator, NULL, value2_p);
+}
+
+
+int
+inode_ctx_set2 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p,
+ uint64_t *value2_p)
{
int ret = 0;
- if (!inode || !xlator)
- return -1;
+ if (!inode || !xlator)
+ return -1;
LOCK (&inode->lock);
{
- ret = __inode_ctx_put (inode, xlator, value);
+ ret = __inode_ctx_set2 (inode, xlator, value1_p, value2_p);
}
UNLOCK (&inode->lock);
- return ret;
+ return ret;
}
int
-__inode_ctx_get (inode_t *inode, xlator_t *xlator, uint64_t *value)
+inode_ctx_set1 (inode_t *inode, xlator_t *xlator, uint64_t *value2_p)
{
- int index = 0;
int ret = 0;
- for (index = 0; index < xlator->ctx->xl_count; index++) {
- if (inode->_ctx[index].key == (uint64_t)(long)xlator)
- break;
+
+ if (!inode || !xlator)
+ return -1;
+
+ LOCK (&inode->lock);
+ {
+ ret = __inode_ctx_set1 (inode, xlator, value2_p);
+ }
+ UNLOCK (&inode->lock);
+
+ return ret;
+}
+int
+inode_ctx_set0 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p)
+{
+ int ret = 0;
+
+ if (!inode || !xlator)
+ return -1;
+
+ LOCK (&inode->lock);
+ {
+ ret = __inode_ctx_set0 (inode, xlator, value1_p);
}
+ UNLOCK (&inode->lock);
- if (index == xlator->ctx->xl_count) {
- ret = -1;
+ return ret;
+}
+
+
+int
+__inode_ctx_get2 (inode_t *inode, xlator_t *xlator, uint64_t *value1,
+ uint64_t *value2)
+{
+ int index = 0;
+ int ret = -1;
+
+ if (!inode || !xlator)
goto out;
+
+ for (index = 0; index < inode->table->ctxcount; index++) {
+ if (inode->_ctx[index].xl_key == xlator)
+ break;
}
- if (value)
- *value = inode->_ctx[index].value;
+ if (index == inode->table->ctxcount)
+ goto out;
+ if (inode->_ctx[index].value1) {
+ if (value1)
+ *value1 = inode->_ctx[index].value1;
+ ret = 0;
+ }
+ if (inode->_ctx[index].value2) {
+ if (value2)
+ *value2 = inode->_ctx[index].value2;
+ ret = 0;
+ }
out:
return ret;
}
-int
-inode_ctx_get (inode_t *inode, xlator_t *xlator, uint64_t *value)
+
+
+int
+__inode_ctx_get0 (inode_t *inode, xlator_t *xlator, uint64_t *value1)
{
+ uint64_t tmp_value = 0;
int ret = 0;
- if (!inode || !xlator)
- return -1;
+ ret = __inode_ctx_get2 (inode, xlator, &tmp_value, NULL);
+ if (!ret)
+ *value1 = tmp_value;
+
+ return ret;
+}
+
+int
+__inode_ctx_get1 (inode_t *inode, xlator_t *xlator, uint64_t *value2)
+{
+ uint64_t tmp_value = 0;
+ int ret = 0;
+
+ ret = __inode_ctx_get2 (inode, xlator, NULL, &tmp_value);
+ if (!ret)
+ *value2 = tmp_value;
+
+ return ret;
+}
+
+
+int
+inode_ctx_get2 (inode_t *inode, xlator_t *xlator, uint64_t *value1,
+ uint64_t *value2)
+{
+ int ret = 0;
+
+ if (!inode || !xlator)
+ return -1;
LOCK (&inode->lock);
{
- ret = __inode_ctx_get (inode, xlator, value);
+ ret = __inode_ctx_get2 (inode, xlator, value1, value2);
}
UNLOCK (&inode->lock);
- return ret;
+ return ret;
}
+int
+inode_ctx_get1 (inode_t *inode, xlator_t *xlator, uint64_t *value2)
+{
+ int ret = 0;
+
+ if (!inode || !xlator)
+ return -1;
+
+ LOCK (&inode->lock);
+ {
+ ret = __inode_ctx_get1 (inode, xlator, value2);
+ }
+ UNLOCK (&inode->lock);
-int
-inode_ctx_del (inode_t *inode, xlator_t *xlator, uint64_t *value)
+ return ret;
+}
+
+int
+inode_ctx_get0 (inode_t *inode, xlator_t *xlator, uint64_t *value1)
{
- int index = 0;
int ret = 0;
- if (!inode || !xlator)
- return -1;
+ if (!inode || !xlator)
+ return -1;
+
+ LOCK (&inode->lock);
+ {
+ ret = __inode_ctx_get0 (inode, xlator, value1);
+ }
+ UNLOCK (&inode->lock);
+
+ return ret;
+}
+
+
+int
+inode_ctx_del2 (inode_t *inode, xlator_t *xlator, uint64_t *value1,
+ uint64_t *value2)
+{
+ int index = 0;
+ int ret = 0;
+
+ if (!inode || !xlator)
+ return -1;
LOCK (&inode->lock);
{
- for (index = 0; index < xlator->ctx->xl_count; index++) {
- if (inode->_ctx[index].key == (uint64_t)(long)xlator)
+ for (index = 0; index < inode->table->ctxcount;
+ index++) {
+ if (inode->_ctx[index].xl_key == xlator)
break;
}
- if (index == xlator->ctx->xl_count) {
+ if (index == inode->table->ctxcount) {
ret = -1;
goto unlock;
}
- if (value)
- *value = inode->_ctx[index].value;
+ if (inode->_ctx[index].value1 && value1)
+ *value1 = inode->_ctx[index].value1;
+ if (inode->_ctx[index].value2 && value2)
+ *value2 = inode->_ctx[index].value2;
- inode->_ctx[index].key = 0;
- inode->_ctx[index].value = 0;
+ inode->_ctx[index].key = 0;
+ inode->_ctx[index].value1 = 0;
+ inode->_ctx[index].value2 = 0;
}
unlock:
UNLOCK (&inode->lock);
- return ret;
+ return ret;
+}
+
+/* function behavior:
+ - if value1 is set, value1 in ctx is reset to 0 with current value passed
+ back in value1 address.
+ - if value2 is set, value2 in ctx is reset to 0 with current value passed
+ back in value2 address.
+ - if both are set, both fields are reset.
+*/
+static int
+__inode_ctx_reset2 (inode_t *inode, xlator_t *xlator, uint64_t *value1,
+ uint64_t *value2)
+{
+ int index = 0;
+ int ret = 0;
+
+ if (!inode || !xlator)
+ return -1;
+
+ LOCK (&inode->lock);
+ {
+ for (index = 0; index < inode->table->ctxcount;
+ index++) {
+ if (inode->_ctx[index].xl_key == xlator)
+ break;
+ }
+
+ if (index == inode->table->ctxcount) {
+ ret = -1;
+ goto unlock;
+ }
+
+ if (inode->_ctx[index].value1 && value1) {
+ *value1 = inode->_ctx[index].value1;
+ inode->_ctx[index].value1 = 0;
+ }
+ if (inode->_ctx[index].value2 && value2) {
+ *value2 = inode->_ctx[index].value2;
+ inode->_ctx[index].value2 = 0;
+ }
+ }
+unlock:
+ UNLOCK (&inode->lock);
+
+ return ret;
+}
+
+int
+inode_ctx_reset2 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p,
+ uint64_t *value2_p)
+{
+ uint64_t tmp_value1 = 0;
+ uint64_t tmp_value2 = 0;
+ int ret = 0;
+
+ ret = __inode_ctx_reset2 (inode, xlator, &tmp_value1, &tmp_value2);
+ if (!ret) {
+ if (value1_p)
+ *value1_p = tmp_value1;
+ if (value2_p)
+ *value2_p = tmp_value2;
+ }
+ return ret;
+}
+
+int
+inode_ctx_reset1 (inode_t *inode, xlator_t *xlator, uint64_t *value2_p)
+{
+ uint64_t tmp_value2 = 0;
+ int ret = 0;
+
+ ret = __inode_ctx_reset2 (inode, xlator, NULL, &tmp_value2);
+
+ if (!ret && value2_p)
+ *value2_p = tmp_value2;
+
+ return ret;
+
+}
+int
+inode_ctx_reset0 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p)
+{
+ uint64_t tmp_value1 = 0;
+ int ret = 0;
+
+ ret = __inode_ctx_reset2 (inode, xlator, &tmp_value1, NULL);
+
+ if (!ret && value1_p)
+ *value1_p = tmp_value1;
+
+ return ret;
}
+
void
inode_dump (inode_t *inode, char *prefix)
{
- char key[GF_DUMP_MAX_BUF_LEN];
- int ret = -1;
- xlator_t *xl = NULL;
- int i = 0;
-
- if (!inode)
+ int ret = -1;
+ xlator_t *xl = NULL;
+ int i = 0;
+ fd_t *fd = NULL;
+ struct _inode_ctx *inode_ctx = NULL;
+ struct list_head fd_list;
+
+ if (!inode)
return;
- ret = TRY_LOCK(&inode->lock);
+ INIT_LIST_HEAD (&fd_list);
+ ret = TRY_LOCK(&inode->lock);
if (ret != 0) {
- gf_log("", GF_LOG_WARNING, "Unable to dump inode"
- " errno: %d", errno);
return;
}
- gf_proc_dump_build_key(key, prefix, "nlookup");
- gf_proc_dump_write(key, "%ld", inode->nlookup);
- gf_proc_dump_build_key(key, prefix, "generation");
- gf_proc_dump_write(key, "%ld", inode->generation);
- gf_proc_dump_build_key(key, prefix, "ref");
- gf_proc_dump_write(key, "%u", inode->ref);
- gf_proc_dump_build_key(key, prefix, "ino");
- gf_proc_dump_write(key, "%ld", inode->ino);
- gf_proc_dump_build_key(key, prefix, "st_mode");
- gf_proc_dump_write(key, "%d", inode->st_mode);
- UNLOCK(&inode->lock);
- if (!inode->_ctx)
- goto out;
-
- for (i = 0; i < inode->table->xl->ctx->xl_count; i++) {
- if (inode->_ctx[i].key) {
- xl = (xlator_t *)(long)inode->_ctx[i].key;
- if (xl->dumpops && xl->dumpops->inodectx)
- xl->dumpops->inodectx (xl, inode);
- }
- }
+ {
+ gf_proc_dump_write("gfid", "%s", uuid_utoa (inode->gfid));
+ gf_proc_dump_write("nlookup", "%ld", inode->nlookup);
+ gf_proc_dump_write("fd-count", "%u", inode->fd_count);
+ gf_proc_dump_write("ref", "%u", inode->ref);
+ gf_proc_dump_write("ia_type", "%d", inode->ia_type);
+ if (inode->_ctx) {
+ inode_ctx = GF_CALLOC (inode->table->ctxcount,
+ sizeof (*inode_ctx),
+ gf_common_mt_inode_ctx);
+ if (inode_ctx == NULL) {
+ goto unlock;
+ }
+
+ for (i = 0; i < inode->table->ctxcount;
+ i++) {
+ inode_ctx[i] = inode->_ctx[i];
+ }
+ }
+
+ if (dump_options.xl_options.dump_fdctx != _gf_true)
+ goto unlock;
+
+
+ list_for_each_entry (fd, &inode->fd_list, inode_list) {
+ fd_ctx_dump (fd, prefix);
+ }
+ }
+unlock:
+ UNLOCK(&inode->lock);
+
+ if (inode_ctx && (dump_options.xl_options.dump_inodectx == _gf_true)) {
+ for (i = 0; i < inode->table->ctxcount; i++) {
+ if (inode_ctx[i].xl_key) {
+ xl = (xlator_t *)(long)inode_ctx[i].xl_key;
+ if (xl->dumpops && xl->dumpops->inodectx)
+ xl->dumpops->inodectx (xl, inode);
+ }
+ }
+ }
+
+ GF_FREE (inode_ctx);
-out:
return;
}
void
inode_table_dump (inode_table_t *itable, char *prefix)
{
-
+
char key[GF_DUMP_MAX_BUF_LEN];
int ret = 0;
if (!itable)
return;
-
+
memset(key, 0, sizeof(key));
- ret = pthread_mutex_trylock(&itable->lock);
+ ret = pthread_mutex_trylock(&itable->lock);
if (ret != 0) {
- gf_log("", GF_LOG_WARNING, "Unable to dump inode table"
- " errno: %d", errno);
return;
}
@@ -1276,7 +1889,7 @@ inode_table_dump (inode_table_t *itable, char *prefix)
gf_proc_dump_write(key, "%d", itable->hashsize);
gf_proc_dump_build_key(key, prefix, "name");
gf_proc_dump_write(key, "%s", itable->name);
-
+
gf_proc_dump_build_key(key, prefix, "lru_limit");
gf_proc_dump_write(key, "%d", itable->lru_limit);
gf_proc_dump_build_key(key, prefix, "active_size");
@@ -1293,3 +1906,98 @@ inode_table_dump (inode_table_t *itable, char *prefix)
pthread_mutex_unlock(&itable->lock);
}
+void
+inode_dump_to_dict (inode_t *inode, char *prefix, dict_t *dict)
+{
+ int ret = -1;
+ char key[GF_DUMP_MAX_BUF_LEN] = {0,};
+
+ ret = TRY_LOCK (&inode->lock);
+ if (ret)
+ return;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.gfid", prefix);
+ ret = dict_set_dynstr (dict, key, gf_strdup (uuid_utoa (inode->gfid)));
+ if (ret)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.nlookup", prefix);
+ ret = dict_set_uint64 (dict, key, inode->nlookup);
+ if (ret)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.ref", prefix);
+ ret = dict_set_uint32 (dict, key, inode->ref);
+ if (ret)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.ia_type", prefix);
+ ret = dict_set_int32 (dict, key, inode->ia_type);
+
+out:
+ UNLOCK (&inode->lock);
+ return;
+}
+
+void
+inode_table_dump_to_dict (inode_table_t *itable, char *prefix, dict_t *dict)
+{
+ char key[GF_DUMP_MAX_BUF_LEN] = {0,};
+ int ret = 0;
+ inode_t *inode = NULL;
+ int count = 0;
+
+ ret = pthread_mutex_trylock (&itable->lock);
+ if (ret)
+ return;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.itable.active_size", prefix);
+ ret = dict_set_uint32 (dict, key, itable->active_size);
+ if (ret)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.itable.lru_size", prefix);
+ ret = dict_set_uint32 (dict, key, itable->lru_size);
+ if (ret)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.itable.purge_size", prefix);
+ ret = dict_set_uint32 (dict, key, itable->purge_size);
+ if (ret)
+ goto out;
+
+ list_for_each_entry (inode, &itable->active, list) {
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.itable.active%d", prefix,
+ count++);
+ inode_dump_to_dict (inode, key, dict);
+ }
+ count = 0;
+
+ list_for_each_entry (inode, &itable->lru, list) {
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.itable.lru%d", prefix,
+ count++);
+ inode_dump_to_dict (inode, key, dict);
+ }
+ count = 0;
+
+ list_for_each_entry (inode, &itable->purge, list) {
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.itable.purge%d", prefix,
+ count++);
+ inode_dump_to_dict (inode, key, dict);
+ }
+
+out:
+ pthread_mutex_unlock (&itable->lock);
+
+ return;
+}