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.c992
1 files changed, 711 insertions, 281 deletions
diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c
index 919f82143..15e0ccf78 100644
--- a/libglusterfs/src/inode.c
+++ b/libglusterfs/src/inode.c
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2007-2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 Affero 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
- Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ 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
@@ -37,13 +28,13 @@
move latest accessed dentry to list_head of inode
*/
-#define INODE_DUMP_LIST(head, key_buf, key_prefix, list_type) \
+#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_build_key(key_buf, key_prefix, \
+ "%s.%d",list_type, i++); \
gf_proc_dump_add_section(key_buf); \
inode_dump(inode, key); \
} \
@@ -93,8 +84,10 @@ __dentry_hash (dentry_t *dentry)
inode_table_t *table = NULL;
int hash = 0;
- if (!dentry)
+ if (!dentry) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "dentry not found");
return;
+ }
table = dentry->inode->table;
hash = hash_dentry (dentry->parent, dentry->name,
@@ -108,8 +101,10 @@ __dentry_hash (dentry_t *dentry)
static int
__is_dentry_hashed (dentry_t *dentry)
{
- if (!dentry)
+ if (!dentry) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "dentry not found");
return 0;
+ }
return !list_empty (&dentry->hash);
}
@@ -118,8 +113,10 @@ __is_dentry_hashed (dentry_t *dentry)
static void
__dentry_unhash (dentry_t *dentry)
{
- if (!dentry)
+ if (!dentry) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "dentry not found");
return;
+ }
list_del_init (&dentry->hash);
}
@@ -128,27 +125,23 @@ __dentry_unhash (dentry_t *dentry)
static void
__dentry_unset (dentry_t *dentry)
{
- struct mem_pool *tmp_pool = NULL;
-
- if (!dentry)
+ if (!dentry) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "dentry not found");
return;
+ }
- tmp_pool = dentry->inode->table->dentry_pool;
__dentry_unhash (dentry);
list_del_init (&dentry->inode_list);
- if (dentry->name)
- GF_FREE (dentry->name);
+ GF_FREE (dentry->name);
if (dentry->parent) {
__inode_unref (dentry->parent);
dentry->parent = NULL;
}
- mem_put (tmp_pool, dentry);
- tmp_pool = NULL;
-
+ mem_put (dentry);
}
@@ -162,16 +155,22 @@ __foreach_ancestor_dentry (dentry_t *dentry,
dentry_t *each = NULL;
int ret = 0;
- if (!dentry)
+ if (!dentry) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "dentry not found");
return 0;
+ }
ret = per_dentry_fn (dentry, data);
- if (ret)
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_WARNING, "per dentry fn returned %d", ret);
goto out;
+ }
parent = dentry->parent;
- if (!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);
@@ -214,8 +213,8 @@ __is_dentry_cyclic (dentry_t *dentry)
gf_log (dentry->inode->table->name, GF_LOG_CRITICAL,
"detected cyclic loop formation during inode linkage."
- " inode (%"PRId64"/%s) linking under itself as %s",
- inode->ino, uuid_utoa (inode->gfid), name);
+ " inode (%s) linking under itself as %s",
+ uuid_utoa (inode->gfid), name);
}
return ret;
@@ -225,8 +224,10 @@ __is_dentry_cyclic (dentry_t *dentry)
static void
__inode_unhash (inode_t *inode)
{
- if (!inode)
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
return;
+ }
list_del_init (&inode->hash);
}
@@ -235,8 +236,10 @@ __inode_unhash (inode_t *inode)
static int
__is_inode_hashed (inode_t *inode)
{
- if (!inode)
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
return 0;
+ }
return !list_empty (&inode->hash);
}
@@ -248,8 +251,10 @@ __inode_hash (inode_t *inode)
inode_table_t *table = NULL;
int hash = 0;
- if (!inode)
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
return;
+ }
table = inode->table;
hash = hash_gfid (inode->gfid, 65536);
@@ -260,16 +265,25 @@ __inode_hash (inode_t *inode)
static dentry_t *
-__dentry_search_for_inode (inode_t *inode, ino_t par, const char *name)
+__dentry_search_for_inode (inode_t *inode, uuid_t pargfid, const char *name)
{
dentry_t *dentry = NULL;
dentry_t *tmp = NULL;
- if (!inode || !name)
+ if (!inode || !name) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode || name not found");
+ return NULL;
+ }
+
+ /* 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 (tmp->parent->ino == par && !strcmp (tmp->name, name)) {
+ if ((uuid_compare (tmp->parent->gfid, pargfid) == 0) &&
+ !strcmp (tmp->name, name)) {
dentry = tmp;
break;
}
@@ -285,17 +299,18 @@ __inode_destroy (inode_t *inode)
int index = 0;
xlator_t *xl = NULL;
xlator_t *old_THIS = NULL;
- struct mem_pool *tmp_pool = NULL;
- if (!inode)
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
return;
+ }
- if (!inode->_ctx)
+ if (!inode->_ctx) {
+ gf_log (THIS->name, GF_LOG_WARNING, "_ctx not found");
goto noctx;
+ }
- tmp_pool = inode->table->inode_pool;
-
- for (index = 0; index < inode->table->xl->graph->xl_count; index++) {
+ 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;
@@ -310,9 +325,7 @@ __inode_destroy (inode_t *inode)
noctx:
LOCK_DESTROY (&inode->lock);
// memset (inode, 0xb, sizeof (*inode));
- mem_put (tmp_pool, inode);
- tmp_pool = NULL;
-
+ mem_put (inode);
}
@@ -333,8 +346,10 @@ __inode_passivate (inode_t *inode)
dentry_t *dentry = NULL;
dentry_t *t = NULL;
- if (!inode)
+ 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++;
@@ -352,8 +367,10 @@ __inode_retire (inode_t *inode)
dentry_t *dentry = NULL;
dentry_t *t = NULL;
- if (!inode)
+ 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++;
@@ -372,7 +389,7 @@ __inode_unref (inode_t *inode)
if (!inode)
return NULL;
- if (inode->ino == 1)
+ if (__is_root_gfid(inode->gfid))
return inode;
GF_ASSERT (inode->ref);
@@ -455,13 +472,14 @@ __dentry_create (inode_t *inode, inode_t *parent, const char *name)
{
dentry_t *newd = NULL;
- if (!inode || !parent || !name)
+ 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) {
- gf_log ("inode", GF_LOG_ERROR, "out of memory");
goto out;
}
@@ -470,8 +488,7 @@ __dentry_create (inode_t *inode, inode_t *parent, const char *name)
newd->name = gf_strdup (name);
if (newd->name == NULL) {
- gf_log ("inode", GF_LOG_ERROR, "out of memory");
- mem_put (parent->table->dentry_pool, newd);
+ mem_put (newd);
newd = NULL;
goto out;
}
@@ -492,12 +509,13 @@ __inode_create (inode_table_t *table)
{
inode_t *newi = NULL;
- if (!table)
+ if (!table) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "table not found");
return NULL;
+ }
newi = mem_get0 (table->inode_pool);
if (!newi) {
- gf_log ("inode", GF_LOG_ERROR, "out of memory");
goto out;
}
@@ -510,14 +528,12 @@ __inode_create (inode_table_t *table)
INIT_LIST_HEAD (&newi->hash);
INIT_LIST_HEAD (&newi->dentry_list);
- newi->_ctx = GF_CALLOC (1, (sizeof (struct _inode_ctx) *
- table->xl->graph->xl_count),
- gf_common_mt_inode_ctx);
-
+ newi->_ctx = GF_CALLOC (1,
+ (sizeof (struct _inode_ctx) * table->ctxcount),
+ gf_common_mt_inode_ctx);
if (newi->_ctx == NULL) {
- gf_log ("inode", GF_LOG_ERROR, "out of memory");
LOCK_DESTROY (&newi->lock);
- mem_put (table->inode_pool, newi);
+ mem_put (newi);
newi = NULL;
goto out;
}
@@ -536,8 +552,10 @@ inode_new (inode_table_t *table)
{
inode_t *inode = NULL;
- if (!table)
+ if (!table) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
return NULL;
+ }
pthread_mutex_lock (&table->lock);
{
@@ -610,8 +628,11 @@ inode_grep (inode_table_t *table, inode_t *parent, const char *name)
inode_t *inode = NULL;
dentry_t *dentry = NULL;
- if (!table || !parent || !name)
+ if (!table || !parent || !name) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING,
+ "table || parent || name not found");
return NULL;
+ }
pthread_mutex_lock (&table->lock);
{
@@ -630,24 +651,94 @@ inode_grep (inode_table_t *table, inode_t *parent, const char *name)
inode_t *
-inode_get (inode_table_t *table, ino_t ino, uint64_t gen)
+inode_resolve (inode_table_t *table, char *path)
+{
+ char *tmp = NULL, *bname = NULL, *str = NULL, *saveptr = NULL;
+ inode_t *inode = NULL, *parent = NULL;
+
+ if ((path == NULL) || (table == NULL)) {
+ goto out;
+ }
+
+ parent = inode_ref (table->root);
+ str = tmp = gf_strdup (path);
+
+ while (1) {
+ bname = strtok_r (str, "/", &saveptr);
+ if (bname == NULL) {
+ break;
+ }
+
+ 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;
+}
+
+
+int
+inode_grep_for_gfid (inode_table_t *table, inode_t *parent, const char *name,
+ uuid_t gfid, ia_type_t *type)
{
- return 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;
+ }
+
+ 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);
+
+ return ret;
}
-static int
+/* return 1 if gfid is of root, 0 if not */
+gf_boolean_t
__is_root_gfid (uuid_t gfid)
{
uuid_t root;
- int ret;
memset (root, 0, 16);
root[15] = 1;
- ret = uuid_compare (gfid, root);
+ if (uuid_compare (gfid, root) == 0)
+ return _gf_true;
- return ret;
+ return _gf_false;
}
@@ -658,10 +749,12 @@ __inode_find (inode_table_t *table, uuid_t gfid)
inode_t *tmp = NULL;
int hash = 0;
- if (!table)
+ if (!table) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "table not found");
goto out;
+ }
- if (__is_root_gfid (gfid) == 0)
+ if (__is_root_gfid (gfid))
return table->root;
hash = hash_gfid (gfid, 65536);
@@ -683,8 +776,10 @@ inode_find (inode_table_t *table, uuid_t gfid)
{
inode_t *inode = NULL;
- if (!table)
+ if (!table) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "table not found");
return NULL;
+ }
pthread_mutex_lock (&table->lock);
{
@@ -715,6 +810,15 @@ __inode_link (inode_t *inode, inode_t *parent, const char *name,
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 (!__is_inode_hashed (inode)) {
@@ -724,25 +828,36 @@ __inode_link (inode_t *inode, inode_t *parent, const char *name,
if (uuid_is_null (iatt->ia_gfid))
return NULL;
- uuid_copy (inode->gfid, iatt->ia_gfid);
- inode->ino = iatt->ia_ino;
- inode->ia_type = iatt->ia_type;
-
- old_inode = __inode_find (table, inode->gfid);
+ old_inode = __inode_find (table, iatt->ia_gfid);
if (old_inode) {
link_inode = old_inode;
} else {
+ uuid_copy (inode->gfid, iatt->ia_gfid);
+ inode->ia_type = iatt->ia_type;
__inode_hash (inode);
}
}
+ if (name) {
+ if (!strcmp(name, ".") || !strcmp(name, ".."))
+ return link_inode;
+ }
+
/* use only link_inode beyond this point */
if (parent) {
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;
@@ -765,8 +880,10 @@ inode_link (inode_t *inode, inode_t *parent, const char *name,
inode_table_t *table = NULL;
inode_t *linked_inode = NULL;
- if (!inode)
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
return NULL;
+ }
table = inode->table;
@@ -790,8 +907,10 @@ inode_lookup (inode_t *inode)
{
inode_table_t *table = NULL;
- if (!inode)
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
return -1;
+ }
table = inode->table;
@@ -810,8 +929,10 @@ inode_forget (inode_t *inode, uint64_t nlookup)
{
inode_table_t *table = NULL;
- if (!inode)
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
return -1;
+ }
table = inode->table;
@@ -826,6 +947,54 @@ 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)
@@ -835,7 +1004,7 @@ __inode_unlink (inode_t *inode, inode_t *parent, const char *name)
if (!inode || !parent || !name)
return;
- dentry = __dentry_search_for_inode (inode, parent->ino, name);
+ dentry = __dentry_search_for_inode (inode, parent->gfid, name);
/* dentry NULL for corrupted backend */
if (dentry)
@@ -848,8 +1017,10 @@ inode_unlink (inode_t *inode, inode_t *parent, const char *name)
{
inode_table_t *table = NULL;
- if (!inode)
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
return;
+ }
table = inode->table;
@@ -868,8 +1039,10 @@ inode_rename (inode_table_t *table, inode_t *srcdir, const char *srcname,
inode_t *dstdir, const char *dstname, inode_t *inode,
struct iatt *iatt)
{
- if (!inode)
+ if (!inode) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found");
return -1;
+ }
table = inode->table;
@@ -914,21 +1087,23 @@ __dentry_search_arbit (inode_t *inode)
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)
+ 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);
}
@@ -946,99 +1121,124 @@ inode_parent (inode_t *inode, ino_t par, const char *name)
int
-inode_path (inode_t *inode, const char *name, char **bufp)
+__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;
-
- if (!inode)
+ 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 (table->name, GF_LOG_CRITICAL,
- "possible infinite loop detected, "
- "forcing break. name=(%s)", name);
- ret = -ENOENT;
- goto unlock;
- }
- }
-
- if ((inode->ino != 1) &&
- (i == 0)) {
- gf_log (table->name, GF_LOG_DEBUG,
- "no dentry for non-root inode %"PRId64,
- inode->ino);
+ 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 unlock;
+ goto out;
}
+ }
- if (name) {
- i++;
- i += strlen (name);
- }
+ if (!__is_root_gfid (itrav->gfid)) {
+ /* "<gfid:00000000-0000-0000-0000-000000000000>"/path */
+ i += GFID_STR_PFX_LEN;
+ }
- ret = i;
- size = i + 1;
- buf = GF_CALLOC (size, sizeof (char), gf_common_mt_char);
- if (buf) {
+ if (name) {
+ i++;
+ i += strlen (name);
+ }
- buf[size - 1] = 0;
+ ret = i;
+ size = i + 1;
+ buf = GF_CALLOC (size, sizeof (char), gf_common_mt_char);
+ if (buf) {
- if (name) {
- len = strlen (name);
- strncpy (buf + (i - len), name, len);
- buf[i-len-1] = '/';
- i -= (len + 1);
- }
+ buf[size - 1] = 0;
- 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;
- } else {
- gf_log (table->name, GF_LOG_ERROR,
- "out of memory");
- ret = -ENOMEM;
+ if (name) {
+ len = strlen (name);
+ strncpy (buf + (i - len), name, len);
+ buf[i-len-1] = '/';
+ i -= (len + 1);
}
+
+ 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);
+ }
+
+ 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] = '>';
+ }
+
+ *bufp = buf;
+ } else {
+ ret = -ENOMEM;
}
-unlock:
- pthread_mutex_unlock (&table->lock);
- if (inode->ino == 1 && !name) {
+out:
+ if (__is_root_gfid (inode->gfid) && !name) {
ret = 1;
- if (buf) {
- GF_FREE (buf);
- }
+ 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;
}
}
+ 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)
{
@@ -1098,8 +1298,8 @@ __inode_table_init_root (inode_table_t *table)
iatt.ia_ino = 1;
iatt.ia_type = IA_IFDIR;
- table->root = root;
__inode_link (root, NULL, NULL, &iatt);
+ table->root = root;
}
@@ -1107,7 +1307,7 @@ 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 *)GF_CALLOC(1, sizeof (*new), gf_common_mt_inode_table_t);
@@ -1115,6 +1315,7 @@ inode_table_new (size_t lru_limit, xlator_t *xl)
return NULL;
new->xl = xl;
+ new->ctxcount = xl->graph->xl_count + 1;
new->lru_limit = lru_limit;
@@ -1126,41 +1327,32 @@ inode_table_new (size_t lru_limit, xlator_t *xl)
new->inode_pool = mem_pool_new (inode_t, lru_limit);
- if (!new->inode_pool) {
- GF_FREE (new);
- return NULL;
- }
+ if (!new->inode_pool)
+ goto out;
new->dentry_pool = mem_pool_new (dentry_t, lru_limit);
- if (!new->dentry_pool) {
- GF_FREE (new);
- return NULL;
- }
+ 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) {
- GF_FREE (new);
- return NULL;
- }
+ 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) {
- GF_FREE (new->inode_hash);
- GF_FREE (new);
- return NULL;
- }
+ if (!new->name_hash)
+ goto out;
- new->fd_mem_pool = mem_pool_new (fd_t, 16384);
+ /* 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) {
- GF_FREE (new->inode_hash);
- GF_FREE (new);
- }
+ if (!new->fd_mem_pool)
+ goto out;
for (i = 0; i < 65536; i++) {
INIT_LIST_HEAD (&new->inode_hash[i]);
@@ -1185,6 +1377,21 @@ inode_table_new (size_t lru_limit, xlator_t *xl)
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;
}
@@ -1206,7 +1413,6 @@ inode_from_path (inode_table_t *itable, const char *path)
/* top-down approach */
pathname = gf_strdup (path);
if (pathname == NULL) {
- gf_log ("inode", GF_LOG_ERROR, "out of memory");
goto out;
}
@@ -1242,8 +1448,7 @@ inode_from_path (inode_table_t *itable, const char *path)
if (parent)
inode_unref (parent);
- if (pathname)
- GF_FREE (pathname);
+ GF_FREE (pathname);
out:
return inode;
@@ -1251,45 +1456,92 @@ out:
int
-__inode_ctx_put2 (inode_t *inode, xlator_t *xlator, uint64_t value1,
- uint64_t value2)
+__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->graph->xl_count; index++) {
+ for (index = 0; index < inode->table->ctxcount; index++) {
if (!inode->_ctx[index].xl_key) {
- if (put_idx == -1)
- put_idx = index;
+ if (set_idx == -1)
+ set_idx = index;
/* dont break, to check if key already exists
further on */
}
if (inode->_ctx[index].xl_key == xlator) {
- put_idx = index;
+ set_idx = index;
break;
}
}
- if (put_idx == -1) {
+ if (set_idx == -1) {
ret = -1;
goto out;;
}
- inode->_ctx[put_idx].xl_key = xlator;
- inode->_ctx[put_idx].value1 = value1;
- inode->_ctx[put_idx].value2 = value2;
+ 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_set0 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p)
+{
+ return __inode_ctx_set2 (inode, xlator, value1_p, NULL);
+}
int
-inode_ctx_put2 (inode_t *inode, xlator_t *xlator, uint64_t value1,
- uint64_t value2)
+__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;
+
+ LOCK (&inode->lock);
+ {
+ ret = __inode_ctx_set2 (inode, xlator, value1_p, value2_p);
+ }
+ UNLOCK (&inode->lock);
+
+ return ret;
+}
+
+int
+inode_ctx_set1 (inode_t *inode, xlator_t *xlator, uint64_t *value2_p)
+{
+ int ret = 0;
+
+ 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;
@@ -1298,7 +1550,7 @@ inode_ctx_put2 (inode_t *inode, xlator_t *xlator, uint64_t value1,
LOCK (&inode->lock);
{
- ret = __inode_ctx_put2 (inode, xlator, value1, value2);
+ ret = __inode_ctx_set0 (inode, xlator, value1_p);
}
UNLOCK (&inode->lock);
@@ -1311,28 +1563,58 @@ __inode_ctx_get2 (inode_t *inode, xlator_t *xlator, uint64_t *value1,
uint64_t *value2)
{
int index = 0;
- int ret = 0;
+ int ret = -1;
if (!inode || !xlator)
- return -1;
+ goto out;
- for (index = 0; index < xlator->graph->xl_count; index++) {
+ for (index = 0; index < inode->table->ctxcount; index++) {
if (inode->_ctx[index].xl_key == xlator)
break;
}
- if (index == xlator->graph->xl_count) {
- ret = -1;
+ 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;
+}
- if (value1)
- *value1 = inode->_ctx[index].value1;
- if (value2)
- *value2 = inode->_ctx[index].value2;
-out:
+int
+__inode_ctx_get0 (inode_t *inode, xlator_t *xlator, uint64_t *value1)
+{
+ uint64_t tmp_value = 0;
+ int ret = 0;
+
+ 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;
}
@@ -1355,6 +1637,40 @@ inode_ctx_get2 (inode_t *inode, xlator_t *xlator, uint64_t *value1,
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);
+
+ return ret;
+}
+
+int
+inode_ctx_get0 (inode_t *inode, xlator_t *xlator, uint64_t *value1)
+{
+ int ret = 0;
+
+ 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,
@@ -1368,19 +1684,20 @@ inode_ctx_del2 (inode_t *inode, xlator_t *xlator, uint64_t *value1,
LOCK (&inode->lock);
{
- for (index = 0; index < xlator->graph->xl_count; index++) {
+ for (index = 0; index < inode->table->ctxcount;
+ index++) {
if (inode->_ctx[index].xl_key == xlator)
break;
}
- if (index == xlator->graph->xl_count) {
+ if (index == inode->table->ctxcount) {
ret = -1;
goto unlock;
}
- if (value1)
+ if (inode->_ctx[index].value1 && value1)
*value1 = inode->_ctx[index].value1;
- if (value2)
+ if (inode->_ctx[index].value2 && value2)
*value2 = inode->_ctx[index].value2;
inode->_ctx[index].key = 0;
@@ -1393,55 +1710,106 @@ unlock:
return ret;
}
-
-int
-__inode_ctx_put (inode_t *inode, xlator_t *key, uint64_t value)
+/* 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)
{
- return __inode_ctx_put2 (inode, key, value, 0);
-}
+ 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;
+ }
-int
-inode_ctx_put (inode_t *inode, xlator_t *key, uint64_t value)
-{
- return inode_ctx_put2 (inode, key, value, 0);
-}
+ 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_get (inode_t *inode, xlator_t *key, uint64_t *value)
+inode_ctx_reset2 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p,
+ uint64_t *value2_p)
{
- return __inode_ctx_get2 (inode, key, value, 0);
-}
+ 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_get (inode_t *inode, xlator_t *key, uint64_t *value)
+inode_ctx_reset1 (inode_t *inode, xlator_t *xlator, uint64_t *value2_p)
{
- return inode_ctx_get2 (inode, key, value, 0);
-}
+ 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_del (inode_t *inode, xlator_t *key, uint64_t *value)
+inode_ctx_reset0 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p)
{
- return inode_ctx_del2 (inode, key, value, 0);
+ 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;
fd_t *fd = NULL;
struct _inode_ctx *inode_ctx = NULL;
- struct fd_wrapper {
- fd_t *fd;
- struct list_head next;
- } *fd_wrapper, *tmp;
struct list_head fd_list;
if (!inode)
@@ -1450,61 +1818,43 @@ inode_dump (inode_t *inode, char *prefix)
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, "gfid");
- gf_proc_dump_write(key, "%s", uuid_utoa (inode->gfid));
- gf_proc_dump_build_key(key, prefix, "nlookup");
- gf_proc_dump_write(key, "%ld", inode->nlookup);
- 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, "ia_type");
- gf_proc_dump_write(key, "%d", inode->ia_type);
+ 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->xl->graph->xl_count,
+ inode_ctx = GF_CALLOC (inode->table->ctxcount,
sizeof (*inode_ctx),
gf_common_mt_inode_ctx);
if (inode_ctx == NULL) {
- gf_log ("", GF_LOG_ERROR, "out of memory");
goto unlock;
}
- for (i = 0; i < inode->table->xl->graph->xl_count; i++) {
+ for (i = 0; i < inode->table->ctxcount;
+ i++) {
inode_ctx[i] = inode->_ctx[i];
}
}
- if (list_empty (&inode->fd_list)) {
- goto unlock;
- }
-
- list_for_each_entry (fd, &inode->fd_list, inode_list) {
- fd_wrapper = GF_CALLOC (1, sizeof (*fd_wrapper),
- gf_common_mt_char);
- if (fd_wrapper == NULL) {
- gf_log ("", GF_LOG_ERROR, "out of memory");
- goto unlock;
- }
+ if (dump_options.xl_options.dump_fdctx != _gf_true)
+ goto unlock;
- INIT_LIST_HEAD (&fd_wrapper->next);
- list_add_tail (&fd_wrapper->next, &fd_list);
- fd_wrapper->fd = _fd_ref (fd);
+ 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->xl->graph->xl_count; i++) {
+ 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)
@@ -1513,21 +1863,7 @@ unlock:
}
}
- if (!list_empty (&fd_list)
- && (dump_options.xl_options.dump_fdctx == _gf_true)) {
- list_for_each_entry_safe (fd_wrapper, tmp, &fd_list,
- next) {
- list_del (&fd_wrapper->next);
- fd_ctx_dump (fd_wrapper->fd, prefix);
-
- fd_unref (fd_wrapper->fd);
- GF_FREE (fd_wrapper);
- }
- }
-
- if (inode_ctx != NULL) {
- GF_FREE (inode_ctx);
- }
+ GF_FREE (inode_ctx);
return;
}
@@ -1546,8 +1882,6 @@ inode_table_dump (inode_table_t *itable, char *prefix)
ret = pthread_mutex_trylock(&itable->lock);
if (ret != 0) {
- gf_log("", GF_LOG_WARNING, "Unable to dump inode table"
- " errno: %d", errno);
return;
}
@@ -1571,3 +1905,99 @@ 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;
+}