summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src/fd.c
diff options
context:
space:
mode:
Diffstat (limited to 'libglusterfs/src/fd.c')
-rw-r--r--libglusterfs/src/fd.c1103
1 files changed, 778 insertions, 325 deletions
diff --git a/libglusterfs/src/fd.c b/libglusterfs/src/fd.c
index 5b2d32bff..36cc4d056 100644
--- a/libglusterfs/src/fd.c
+++ b/libglusterfs/src/fd.c
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2007-2009 Z RESEARCH, Inc. <http://www.zresearch.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 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/>.
+ 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.
*/
#include "fd.h"
@@ -30,33 +21,12 @@
#endif
-static uint32_t
+static int
gf_fd_fdtable_expand (fdtable_t *fdtable, uint32_t nr);
-static fd_t *
-_fd_ref (fd_t *fd);
-
-/*
- Allocate in memory chunks of power of 2 starting from 1024B
- Assumes fdtable->lock is held
-*/
-static inline uint32_t
-gf_roundup_power_of_two (uint32_t nr)
-{
- uint32_t result = 1;
-
- if (nr < 0) {
- gf_log ("server-protocol/fd",
- GF_LOG_ERROR,
- "Negative number passed");
- return -1;
- }
-
- while (result <= nr)
- result *= 2;
- return result;
-}
+fd_t *
+__fd_ref (fd_t *fd);
static int
gf_fd_chain_fd_entries (fdentry_t *entries, uint32_t startidx,
@@ -64,8 +34,10 @@ gf_fd_chain_fd_entries (fdentry_t *entries, uint32_t startidx,
{
uint32_t i = 0;
- if (!entries)
+ if (!entries) {
+ gf_log_callingfn ("fd", GF_LOG_WARNING, "!entries");
return -1;
+ }
/* Chain only till the second to last entry because we want to
* ensure that the last entry has GF_FDTABLE_END.
@@ -80,33 +52,38 @@ gf_fd_chain_fd_entries (fdentry_t *entries, uint32_t startidx,
}
-static uint32_t
+static int
gf_fd_fdtable_expand (fdtable_t *fdtable, uint32_t nr)
{
- fdentry_t *oldfds = NULL;
- uint32_t oldmax_fds = -1;
-
- if (fdtable == NULL || nr < 0)
- {
- gf_log ("fd", GF_LOG_ERROR, "invalid argument");
- return EINVAL;
- }
-
- nr /= (1024 / sizeof (fdentry_t));
- nr = gf_roundup_power_of_two (nr + 1);
- nr *= (1024 / sizeof (fdentry_t));
-
- oldfds = fdtable->fdentries;
- oldmax_fds = fdtable->max_fds;
-
- fdtable->fdentries = CALLOC (nr, sizeof (fdentry_t));
- ERR_ABORT (fdtable->fdentries);
- fdtable->max_fds = nr;
-
- if (oldfds) {
- uint32_t cpy = oldmax_fds * sizeof (fdentry_t);
- memcpy (fdtable->fdentries, oldfds, cpy);
- }
+ fdentry_t *oldfds = NULL;
+ uint32_t oldmax_fds = -1;
+ int ret = -1;
+
+ if (fdtable == NULL || nr < 0) {
+ gf_log_callingfn ("fd", GF_LOG_ERROR, "invalid argument");
+ ret = EINVAL;
+ goto out;
+ }
+
+ nr /= (1024 / sizeof (fdentry_t));
+ nr = gf_roundup_next_power_of_two (nr + 1);
+ nr *= (1024 / sizeof (fdentry_t));
+
+ oldfds = fdtable->fdentries;
+ oldmax_fds = fdtable->max_fds;
+
+ fdtable->fdentries = GF_CALLOC (nr, sizeof (fdentry_t),
+ gf_common_mt_fdentry_t);
+ if (!fdtable->fdentries) {
+ ret = ENOMEM;
+ goto out;
+ }
+ fdtable->max_fds = nr;
+
+ if (oldfds) {
+ uint32_t cpy = oldmax_fds * sizeof (fdentry_t);
+ memcpy (fdtable->fdentries, oldfds, cpy);
+ }
gf_fd_chain_fd_entries (fdtable->fdentries, oldmax_fds,
fdtable->max_fds);
@@ -116,41 +93,47 @@ gf_fd_fdtable_expand (fdtable_t *fdtable, uint32_t nr)
* using the expanded table.
*/
fdtable->first_free = oldmax_fds;
- FREE (oldfds);
- return 0;
+ GF_FREE (oldfds);
+ ret = 0;
+out:
+ return ret;
}
+
fdtable_t *
-gf_fd_fdtable_alloc (void)
+gf_fd_fdtable_alloc (void)
{
- fdtable_t *fdtable = NULL;
+ fdtable_t *fdtable = NULL;
- fdtable = CALLOC (1, sizeof (*fdtable));
- if (!fdtable)
- return NULL;
+ fdtable = GF_CALLOC (1, sizeof (*fdtable), gf_common_mt_fdtable_t);
+ if (!fdtable)
+ return NULL;
- pthread_mutex_init (&fdtable->lock, NULL);
+ pthread_mutex_init (&fdtable->lock, NULL);
- pthread_mutex_lock (&fdtable->lock);
- {
- gf_fd_fdtable_expand (fdtable, 0);
- }
- pthread_mutex_unlock (&fdtable->lock);
+ pthread_mutex_lock (&fdtable->lock);
+ {
+ gf_fd_fdtable_expand (fdtable, 0);
+ }
+ pthread_mutex_unlock (&fdtable->lock);
- return fdtable;
+ return fdtable;
}
-fdentry_t *
+
+static fdentry_t *
__gf_fd_fdtable_get_all_fds (fdtable_t *fdtable, uint32_t *count)
{
fdentry_t *fdentries = NULL;
if (count == NULL) {
+ gf_log_callingfn ("fd", GF_LOG_WARNING, "!count");
goto out;
}
fdentries = fdtable->fdentries;
- fdtable->fdentries = calloc (fdtable->max_fds, sizeof (fdentry_t));
+ fdtable->fdentries = GF_CALLOC (fdtable->max_fds, sizeof (fdentry_t),
+ gf_common_mt_fdentry_t);
gf_fd_chain_fd_entries (fdtable->fdentries, 0, fdtable->max_fds);
*count = fdtable->max_fds;
@@ -158,10 +141,12 @@ out:
return fdentries;
}
+
fdentry_t *
gf_fd_fdtable_get_all_fds (fdtable_t *fdtable, uint32_t *count)
{
fdentry_t *entries = NULL;
+
if (fdtable) {
pthread_mutex_lock (&fdtable->lock);
{
@@ -173,26 +158,76 @@ gf_fd_fdtable_get_all_fds (fdtable_t *fdtable, uint32_t *count)
return entries;
}
-void
+
+static fdentry_t *
+__gf_fd_fdtable_copy_all_fds (fdtable_t *fdtable, uint32_t *count)
+{
+ fdentry_t *fdentries = NULL;
+ int i = 0;
+
+ if (count == NULL) {
+ gf_log_callingfn ("fd", GF_LOG_WARNING, "!count");
+ goto out;
+ }
+
+ fdentries = GF_CALLOC (fdtable->max_fds, sizeof (fdentry_t),
+ gf_common_mt_fdentry_t);
+ if (fdentries == NULL) {
+ goto out;
+ }
+
+ *count = fdtable->max_fds;
+
+ for (i = 0; i < fdtable->max_fds; i++) {
+ if (fdtable->fdentries[i].fd != NULL) {
+ fdentries[i].fd = fd_ref (fdtable->fdentries[i].fd);
+ }
+ }
+
+out:
+ return fdentries;
+}
+
+
+fdentry_t *
+gf_fd_fdtable_copy_all_fds (fdtable_t *fdtable, uint32_t *count)
+{
+ fdentry_t *entries = NULL;
+
+ if (fdtable) {
+ pthread_mutex_lock (&fdtable->lock);
+ {
+ entries = __gf_fd_fdtable_copy_all_fds (fdtable, count);
+ }
+ pthread_mutex_unlock (&fdtable->lock);
+ }
+
+ return entries;
+}
+
+
+void
gf_fd_fdtable_destroy (fdtable_t *fdtable)
{
struct list_head list = {0, };
fd_t *fd = NULL;
fdentry_t *fdentries = NULL;
uint32_t fd_count = 0;
- int32_t i = 0;
+ int32_t i = 0;
INIT_LIST_HEAD (&list);
- if (!fdtable)
+ if (!fdtable) {
+ gf_log_callingfn ("fd", GF_LOG_WARNING, "!fdtable");
return;
+ }
- pthread_mutex_lock (&fdtable->lock);
- {
+ pthread_mutex_lock (&fdtable->lock);
+ {
fdentries = __gf_fd_fdtable_get_all_fds (fdtable, &fd_count);
- FREE (fdtable->fdentries);
- }
- pthread_mutex_unlock (&fdtable->lock);
+ GF_FREE (fdtable->fdentries);
+ }
+ pthread_mutex_unlock (&fdtable->lock);
if (fdentries != NULL) {
for (i = 0; i < fd_count; i++) {
@@ -202,53 +237,53 @@ gf_fd_fdtable_destroy (fdtable_t *fdtable)
}
}
- FREE (fdentries);
- pthread_mutex_destroy (&fdtable->lock);
- FREE (fdtable);
- }
+ GF_FREE (fdentries);
+ pthread_mutex_destroy (&fdtable->lock);
+ GF_FREE (fdtable);
+ }
}
-int32_t
+
+int
gf_fd_unused_get (fdtable_t *fdtable, fd_t *fdptr)
{
- int32_t fd = -1;
+ int32_t fd = -1;
fdentry_t *fde = NULL;
- int error;
+ int error;
int alloc_attempts = 0;
-
- if (fdtable == NULL || fdptr == NULL)
- {
- gf_log ("fd", GF_LOG_ERROR, "invalid argument");
- return EINVAL;
- }
-
- pthread_mutex_lock (&fdtable->lock);
- {
-fd_alloc_try_again:
+
+ if (fdtable == NULL || fdptr == NULL) {
+ gf_log_callingfn ("fd", GF_LOG_ERROR, "invalid argument");
+ return EINVAL;
+ }
+
+ pthread_mutex_lock (&fdtable->lock);
+ {
+ fd_alloc_try_again:
if (fdtable->first_free != GF_FDTABLE_END) {
fde = &fdtable->fdentries[fdtable->first_free];
fd = fdtable->first_free;
fdtable->first_free = fde->next_free;
fde->next_free = GF_FDENTRY_ALLOCATED;
fde->fd = fdptr;
- } else {
+ } else {
/* If this is true, there is something
* seriously wrong with our data structures.
*/
if (alloc_attempts >= 2) {
- gf_log ("server-protocol.c", GF_LOG_ERROR,
- "Multiple attempts to expand fd table"
+ gf_log ("fd", GF_LOG_ERROR,
+ "multiple attempts to expand fd table"
" have failed.");
goto out;
}
error = gf_fd_fdtable_expand (fdtable,
fdtable->max_fds + 1);
- if (error) {
- gf_log ("server-protocol.c",
- GF_LOG_ERROR,
- "Cannot expand fdtable:%s", strerror (error));
+ if (error) {
+ gf_log ("fd", GF_LOG_ERROR,
+ "Cannot expand fdtable: %s",
+ strerror (error));
goto out;
- }
+ }
++alloc_attempts;
/* At this point, the table stands expanded
* with the first_free referring to the first
@@ -257,41 +292,43 @@ fd_alloc_try_again:
* above logic should just work.
*/
goto fd_alloc_try_again;
- }
- }
+ }
+ }
out:
- pthread_mutex_unlock (&fdtable->lock);
+ pthread_mutex_unlock (&fdtable->lock);
- return fd;
+ return fd;
}
-inline void
+inline void
gf_fd_put (fdtable_t *fdtable, int32_t fd)
{
- fd_t *fdptr = NULL;
+ fd_t *fdptr = NULL;
fdentry_t *fde = NULL;
- if (fdtable == NULL || fd < 0)
- {
- gf_log ("fd", GF_LOG_ERROR, "invalid argument");
- return;
- }
-
- if (!(fd < fdtable->max_fds))
- {
- gf_log ("fd", GF_LOG_ERROR, "invalid argument");
- return;
- }
-
- pthread_mutex_lock (&fdtable->lock);
- {
+ if (fd == -2)
+ /* anonymous fd */
+ return;
+
+ if (fdtable == NULL || fd < 0) {
+ gf_log_callingfn ("fd", GF_LOG_ERROR, "invalid argument");
+ return;
+ }
+
+ if (!(fd < fdtable->max_fds)) {
+ gf_log_callingfn ("fd", GF_LOG_ERROR, "invalid argument");
+ return;
+ }
+
+ pthread_mutex_lock (&fdtable->lock);
+ {
fde = &fdtable->fdentries[fd];
/* If the entry is not allocated, put operation must return
* without doing anything.
* This has the potential of masking out any bugs in a user of
* fd that ends up calling gf_fd_put twice for the same fd or
- * for an unallocated fd, but thats a price we have to pay for
+ * for an unallocated fd, but it is a price we have to pay for
* ensuring sanity of our fd-table.
*/
if (fde->next_free != GF_FDENTRY_ALLOCATED)
@@ -300,150 +337,213 @@ gf_fd_put (fdtable_t *fdtable, int32_t fd)
fde->fd = NULL;
fde->next_free = fdtable->first_free;
fdtable->first_free = fd;
- }
+ }
+unlock_out:
+ pthread_mutex_unlock (&fdtable->lock);
+
+ if (fdptr) {
+ fd_unref (fdptr);
+ }
+}
+
+
+inline void
+gf_fdptr_put (fdtable_t *fdtable, fd_t *fd)
+{
+ fdentry_t *fde = NULL;
+ int32_t i = 0;
+
+ if ((fdtable == NULL) || (fd == NULL)) {
+ gf_log_callingfn ("fd", GF_LOG_ERROR, "invalid argument");
+ return;
+ }
+
+ pthread_mutex_lock (&fdtable->lock);
+ {
+ for (i = 0; i < fdtable->max_fds; i++) {
+ if (fdtable->fdentries[i].fd == fd) {
+ fde = &fdtable->fdentries[i];
+ break;
+ }
+ }
+
+ if (fde == NULL) {
+ gf_log_callingfn ("fd", GF_LOG_WARNING,
+ "fd (%p) is not present in fdtable", fd);
+ goto unlock_out;
+ }
+
+ /* If the entry is not allocated, put operation must return
+ * without doing anything.
+ * This has the potential of masking out any bugs in a user of
+ * fd that ends up calling gf_fd_put twice for the same fd or
+ * for an unallocated fd, but it is a price we have to pay for
+ * ensuring sanity of our fd-table.
+ */
+ if (fde->next_free != GF_FDENTRY_ALLOCATED)
+ goto unlock_out;
+ fde->fd = NULL;
+ fde->next_free = fdtable->first_free;
+ fdtable->first_free = i;
+ }
unlock_out:
- pthread_mutex_unlock (&fdtable->lock);
+ pthread_mutex_unlock (&fdtable->lock);
- if (fdptr) {
- fd_unref (fdptr);
- }
+ if ((fd != NULL) && (fde != NULL)) {
+ fd_unref (fd);
+ }
}
fd_t *
gf_fd_fdptr_get (fdtable_t *fdtable, int64_t fd)
{
- fd_t *fdptr = NULL;
-
- if (fdtable == NULL || fd < 0)
- {
- gf_log ("fd", GF_LOG_ERROR, "invalid argument");
- errno = EINVAL;
- return NULL;
- }
-
- if (!(fd < fdtable->max_fds))
- {
- gf_log ("fd", GF_LOG_ERROR, "invalid argument");
- errno = EINVAL;
- return NULL;
- }
-
- pthread_mutex_lock (&fdtable->lock);
- {
- fdptr = fdtable->fdentries[fd].fd;
- if (fdptr) {
- fd_ref (fdptr);
- }
- }
- pthread_mutex_unlock (&fdtable->lock);
-
- return fdptr;
+ fd_t *fdptr = NULL;
+
+ if (fdtable == NULL || fd < 0) {
+ gf_log_callingfn ("fd", GF_LOG_ERROR, "invalid argument");
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if (!(fd < fdtable->max_fds)) {
+ gf_log_callingfn ("fd", GF_LOG_ERROR, "invalid argument");
+ errno = EINVAL;
+ return NULL;
+ }
+
+ pthread_mutex_lock (&fdtable->lock);
+ {
+ fdptr = fdtable->fdentries[fd].fd;
+ if (fdptr) {
+ fd_ref (fdptr);
+ }
+ }
+ pthread_mutex_unlock (&fdtable->lock);
+
+ return fdptr;
}
+
fd_t *
-_fd_ref (fd_t *fd)
+__fd_ref (fd_t *fd)
{
- ++fd->refcount;
-
- return fd;
+ ++fd->refcount;
+
+ return fd;
}
+
fd_t *
fd_ref (fd_t *fd)
{
- fd_t *refed_fd = NULL;
+ fd_t *refed_fd = NULL;
- if (!fd) {
- gf_log ("fd", GF_LOG_ERROR, "@fd=%p", fd);
- return NULL;
- }
+ if (!fd) {
+ gf_log_callingfn ("fd", GF_LOG_ERROR, "null fd");
+ return NULL;
+ }
+
+ LOCK (&fd->inode->lock);
+ refed_fd = __fd_ref (fd);
+ UNLOCK (&fd->inode->lock);
- LOCK (&fd->inode->lock);
- refed_fd = _fd_ref (fd);
- UNLOCK (&fd->inode->lock);
-
- return refed_fd;
+ return refed_fd;
}
+
fd_t *
-_fd_unref (fd_t *fd)
+__fd_unref (fd_t *fd)
{
- assert (fd->refcount);
+ GF_ASSERT (fd->refcount);
+
+ --fd->refcount;
- --fd->refcount;
+ if (fd->refcount == 0) {
+ list_del_init (&fd->inode_list);
+ }
- if (fd->refcount == 0){
- list_del_init (&fd->inode_list);
- }
-
- return fd;
+ return fd;
}
+
static void
fd_destroy (fd_t *fd)
{
xlator_t *xl = NULL;
- int i = 0;
+ int i = 0;
+ xlator_t *old_THIS = NULL;
if (fd == NULL){
- gf_log ("xlator", GF_LOG_ERROR, "invalid arugument");
+ gf_log_callingfn ("xlator", GF_LOG_ERROR, "invalid argument");
goto out;
}
-
+
if (fd->inode == NULL){
- gf_log ("xlator", GF_LOG_ERROR, "fd->inode is NULL");
+ gf_log_callingfn ("xlator", GF_LOG_ERROR, "fd->inode is NULL");
goto out;
}
- if (!fd->_ctx)
- goto out;
-
- if (S_ISDIR (fd->inode->st_mode)) {
- for (i = 0; i < fd->inode->table->xl->ctx->xl_count; i++) {
- if (fd->_ctx[i].key) {
- xl = (xlator_t *)(long)fd->_ctx[i].key;
- if (xl->cbks->releasedir)
- xl->cbks->releasedir (xl, fd);
- }
- }
+ if (!fd->_ctx)
+ goto out;
+
+ if (IA_ISDIR (fd->inode->ia_type)) {
+ for (i = 0; i < fd->xl_count; i++) {
+ if (fd->_ctx[i].key) {
+ xl = fd->_ctx[i].xl_key;
+ old_THIS = THIS;
+ THIS = xl;
+ if (xl->cbks->releasedir)
+ xl->cbks->releasedir (xl, fd);
+ THIS = old_THIS;
+ }
+ }
} else {
- for (i = 0; i < fd->inode->table->xl->ctx->xl_count; i++) {
- if (fd->_ctx[i].key) {
- xl = (xlator_t *)(long)fd->_ctx[i].key;
- if (xl->cbks->release)
- xl->cbks->release (xl, fd);
- }
- }
- }
-
+ for (i = 0; i < fd->xl_count; i++) {
+ if (fd->_ctx[i].key) {
+ xl = fd->_ctx[i].xl_key;
+ old_THIS = THIS;
+ THIS = xl;
+ if (xl->cbks->release)
+ xl->cbks->release (xl, fd);
+ THIS = old_THIS;
+ }
+ }
+ }
+
LOCK_DESTROY (&fd->lock);
- FREE (fd->_ctx);
+ GF_FREE (fd->_ctx);
+ LOCK (&fd->inode->lock);
+ {
+ fd->inode->fd_count--;
+ }
+ UNLOCK (&fd->inode->lock);
inode_unref (fd->inode);
fd->inode = (inode_t *)0xaaaaaaaa;
- FREE (fd);
-
+ fd_lk_ctx_unref (fd->lk_ctx);
+ mem_put (fd);
out:
return;
}
+
void
fd_unref (fd_t *fd)
{
int32_t refcount = 0;
if (!fd) {
- gf_log ("fd.c", GF_LOG_ERROR, "fd is NULL");
+ gf_log_callingfn ("fd", GF_LOG_ERROR, "fd is NULL");
return;
}
-
+
LOCK (&fd->inode->lock);
{
- _fd_unref (fd);
+ __fd_unref (fd);
refcount = fd->refcount;
}
UNLOCK (&fd->inode->lock);
-
+
if (refcount == 0) {
fd_destroy (fd);
}
@@ -451,129 +551,336 @@ fd_unref (fd_t *fd)
return ;
}
+
fd_t *
-fd_bind (fd_t *fd)
+__fd_bind (fd_t *fd)
{
- inode_t *inode = fd->inode;
+ list_del_init (&fd->inode_list);
+ list_add (&fd->inode_list, &fd->inode->fd_list);
+ fd->inode->fd_count++;
- if (!fd) {
- gf_log ("fd.c", GF_LOG_ERROR, "fd is NULL");
+ return fd;
+}
+
+
+fd_t *
+fd_bind (fd_t *fd)
+{
+ if (!fd || !fd->inode) {
+ gf_log_callingfn ("fd", GF_LOG_ERROR, "!fd || !fd->inode");
return NULL;
}
- LOCK (&inode->lock);
+ LOCK (&fd->inode->lock);
{
- list_add (&fd->inode_list, &inode->fd_list);
+ fd = __fd_bind (fd);
}
- UNLOCK (&inode->lock);
-
+ UNLOCK (&fd->inode->lock);
+
return fd;
}
-fd_t *
-fd_create (inode_t *inode, pid_t pid)
+
+static fd_t *
+__fd_create (inode_t *inode, uint64_t pid)
{
fd_t *fd = NULL;
-
+
if (inode == NULL) {
- gf_log ("fd", GF_LOG_ERROR, "invalid argument");
+ gf_log_callingfn ("fd", GF_LOG_ERROR, "invalid argument");
return NULL;
}
-
- fd = CALLOC (1, sizeof (fd_t));
- ERR_ABORT (fd);
-
- fd->_ctx = CALLOC (1, (sizeof (struct _fd_ctx) *
- inode->table->xl->ctx->xl_count));
+
+ fd = mem_get0 (inode->table->fd_mem_pool);
+ if (!fd)
+ goto out;
+
+ fd->xl_count = inode->table->xl->graph->xl_count + 1;
+
+ fd->_ctx = GF_CALLOC (1, (sizeof (struct _fd_ctx) * fd->xl_count),
+ gf_common_mt_fd_ctx);
+ if (!fd->_ctx)
+ goto free_fd;
+
+ fd->lk_ctx = fd_lk_ctx_create ();
+ if (!fd->lk_ctx)
+ goto free_fd_ctx;
+
fd->inode = inode_ref (inode);
fd->pid = pid;
INIT_LIST_HEAD (&fd->inode_list);
-
+
LOCK_INIT (&fd->lock);
+out:
+ return fd;
+
+free_fd_ctx:
+ GF_FREE (fd->_ctx);
+free_fd:
+ mem_put (fd);
+
+ return NULL;
+}
+
+
+fd_t *
+fd_create (inode_t *inode, pid_t pid)
+{
+ fd_t *fd = NULL;
+
+ fd = __fd_create (inode, (uint64_t)pid);
+ if (!fd)
+ goto out;
+
+ fd = fd_ref (fd);
+
+out:
+ return fd;
+}
+
+fd_t *
+fd_create_uint64 (inode_t *inode, uint64_t pid)
+{
+ fd_t *fd = NULL;
+
+ fd = __fd_create (inode, pid);
+ if (!fd)
+ goto out;
+
+ fd = fd_ref (fd);
+
+out:
+ return fd;
+}
+
+
+static fd_t *
+__fd_lookup (inode_t *inode, uint64_t pid)
+{
+ fd_t *iter_fd = NULL;
+ fd_t *fd = NULL;
+
+ if (list_empty (&inode->fd_list))
+ return NULL;
+
+
+ list_for_each_entry (iter_fd, &inode->fd_list, inode_list) {
+ if (iter_fd->anonymous)
+ /* If someone was interested in getting an
+ anonymous fd (or was OK getting an anonymous fd),
+ they can as well call fd_anonymous() directly */
+ continue;
+
+ if (!pid || iter_fd->pid == pid) {
+ fd = __fd_ref (iter_fd);
+ break;
+ }
+ }
+
+ return fd;
+}
+
+
+fd_t *
+fd_lookup (inode_t *inode, pid_t pid)
+{
+ fd_t *fd = NULL;
+
+ if (!inode) {
+ gf_log_callingfn ("fd", GF_LOG_WARNING, "!inode");
+ return NULL;
+ }
LOCK (&inode->lock);
- fd = _fd_ref (fd);
+ {
+ fd = __fd_lookup (inode, (uint64_t)pid);
+ }
UNLOCK (&inode->lock);
return fd;
}
fd_t *
-fd_lookup (inode_t *inode, pid_t pid)
+fd_lookup_uint64 (inode_t *inode, uint64_t pid)
{
fd_t *fd = NULL;
- fd_t *iter_fd = NULL;
+
+ if (!inode) {
+ gf_log_callingfn ("fd", GF_LOG_WARNING, "!inode");
+ return NULL;
+ }
LOCK (&inode->lock);
{
- if (list_empty (&inode->fd_list)) {
- fd = NULL;
- } else {
- list_for_each_entry (iter_fd, &inode->fd_list, inode_list) {
- if (pid) {
- if (iter_fd->pid == pid) {
- fd = _fd_ref (iter_fd);
- break;
- }
- } else {
- fd = _fd_ref (iter_fd);
- break;
- }
- }
+ fd = __fd_lookup (inode, pid);
+ }
+ UNLOCK (&inode->lock);
+
+ return fd;
+}
+
+static fd_t *
+__fd_lookup_anonymous (inode_t *inode)
+{
+ fd_t *iter_fd = NULL;
+ fd_t *fd = NULL;
+
+ if (list_empty (&inode->fd_list))
+ return NULL;
+
+ list_for_each_entry (iter_fd, &inode->fd_list, inode_list) {
+ if (iter_fd->anonymous) {
+ fd = __fd_ref (iter_fd);
+ break;
}
}
+
+ return fd;
+}
+
+static fd_t *
+__fd_anonymous (inode_t *inode)
+{
+ fd_t *fd = NULL;
+
+ fd = __fd_lookup_anonymous (inode);
+
+ /* if (fd); then we already have increased the refcount in
+ __fd_lookup_anonymous(), so no need of one more fd_ref().
+ if (!fd); then both create and bind wont bump up the ref
+ count, so we have to call fd_ref() after bind. */
+ if (!fd) {
+ fd = __fd_create (inode, 0);
+
+ if (!fd)
+ return NULL;
+
+ fd->anonymous = _gf_true;
+
+ __fd_bind (fd);
+
+ __fd_ref (fd);
+ }
+
+ return fd;
+}
+
+
+fd_t *
+fd_anonymous (inode_t *inode)
+{
+ fd_t *fd = NULL;
+
+ LOCK (&inode->lock);
+ {
+ fd = __fd_anonymous (inode);
+ }
+ UNLOCK (&inode->lock);
+
+ return fd;
+}
+
+fd_t*
+fd_lookup_anonymous (inode_t *inode)
+{
+ fd_t *fd = NULL;
+
+ if (!inode) {
+ gf_log_callingfn ("fd", GF_LOG_WARNING, "!inode");
+ return NULL;
+ }
+
+ LOCK (&inode->lock);
+ {
+ fd = __fd_lookup_anonymous (inode);
+ }
UNLOCK (&inode->lock);
-
return fd;
}
+gf_boolean_t
+fd_is_anonymous (fd_t *fd)
+{
+ return (fd && fd->anonymous);
+}
+
+
uint8_t
fd_list_empty (inode_t *inode)
{
- uint8_t empty = 0;
+ uint8_t empty = 0;
LOCK (&inode->lock);
{
empty = list_empty (&inode->fd_list);
}
UNLOCK (&inode->lock);
-
+
return empty;
}
+
int
__fd_ctx_set (fd_t *fd, xlator_t *xlator, uint64_t value)
{
- int index = 0;
- int ret = 0;
- int set_idx = -1;
+ int index = 0, new_xl_count = 0;
+ int ret = 0;
+ int set_idx = -1;
+ void *begin = NULL;
+ size_t diff = 0;
+ struct _fd_ctx *tmp = NULL;
if (!fd || !xlator)
return -1;
-
- for (index = 0; index < xlator->ctx->xl_count; index++) {
+
+ for (index = 0; index < fd->xl_count; index++) {
if (!fd->_ctx[index].key) {
if (set_idx == -1)
set_idx = index;
/* dont break, to check if key already exists
further on */
}
- if (fd->_ctx[index].key == (uint64_t)(long) xlator) {
+ if (fd->_ctx[index].xl_key == xlator) {
set_idx = index;
break;
}
}
-
+
if (set_idx == -1) {
- ret = -1;
- goto out;
+ set_idx = fd->xl_count;
+
+ new_xl_count = fd->xl_count + xlator->graph->xl_count;
+
+ tmp = GF_REALLOC (fd->_ctx,
+ (sizeof (struct _fd_ctx)
+ * new_xl_count));
+ if (tmp == NULL) {
+ gf_log_callingfn (THIS->name, GF_LOG_WARNING,
+ "realloc of fd->_ctx for fd "
+ "(ptr: %p) failed, cannot set the key"
+ , fd);
+ ret = -1;
+ goto out;
+ }
+
+ fd->_ctx = tmp;
+
+ begin = fd->_ctx;
+ begin += (fd->xl_count * sizeof (struct _fd_ctx));
+
+ diff = (new_xl_count - fd->xl_count )
+ * sizeof (struct _fd_ctx);
+
+ memset (begin, 0, diff);
+
+ fd->xl_count = new_xl_count;
}
-
- fd->_ctx[set_idx].key = (uint64_t)(long) xlator;
- fd->_ctx[set_idx].value = value;
+
+ fd->_ctx[set_idx].xl_key = xlator;
+ fd->_ctx[set_idx].value1 = value;
out:
- return ret;
+ return ret;
}
@@ -582,9 +889,11 @@ fd_ctx_set (fd_t *fd, xlator_t *xlator, uint64_t value)
{
int ret = 0;
- if (!fd || !xlator)
+ if (!fd || !xlator) {
+ gf_log_callingfn ("", GF_LOG_WARNING, "%p %p", fd, xlator);
return -1;
-
+ }
+
LOCK (&fd->lock);
{
ret = __fd_ctx_set (fd, xlator, value);
@@ -595,40 +904,40 @@ fd_ctx_set (fd_t *fd, xlator_t *xlator, uint64_t value)
}
-int
+int
__fd_ctx_get (fd_t *fd, xlator_t *xlator, uint64_t *value)
{
- int index = 0;
+ int index = 0;
int ret = 0;
- if (!fd || !xlator)
- return -1;
-
- for (index = 0; index < xlator->ctx->xl_count; index++) {
- if (fd->_ctx[index].key == (uint64_t)(long)xlator)
+ if (!fd || !xlator)
+ return -1;
+
+ for (index = 0; index < fd->xl_count; index++) {
+ if (fd->_ctx[index].xl_key == xlator)
break;
}
-
- if (index == xlator->ctx->xl_count) {
+
+ if (index == fd->xl_count) {
ret = -1;
goto out;
}
- if (value)
- *value = fd->_ctx[index].value;
-
+ if (value)
+ *value = fd->_ctx[index].value1;
+
out:
- return ret;
+ return ret;
}
-int
+int
fd_ctx_get (fd_t *fd, xlator_t *xlator, uint64_t *value)
{
int ret = 0;
- if (!fd || !xlator)
- return -1;
+ if (!fd || !xlator)
+ return -1;
LOCK (&fd->lock);
{
@@ -640,44 +949,44 @@ fd_ctx_get (fd_t *fd, xlator_t *xlator, uint64_t *value)
}
-int
+int
__fd_ctx_del (fd_t *fd, xlator_t *xlator, uint64_t *value)
{
- int index = 0;
+ int index = 0;
int ret = 0;
- if (!fd || !xlator)
- return -1;
-
- for (index = 0; index < xlator->ctx->xl_count; index++) {
- if (fd->_ctx[index].key == (uint64_t)(long)xlator)
+ if (!fd || !xlator)
+ return -1;
+
+ for (index = 0; index < fd->xl_count; index++) {
+ if (fd->_ctx[index].xl_key == xlator)
break;
}
-
- if (index == xlator->ctx->xl_count) {
+
+ if (index == fd->xl_count) {
ret = -1;
goto out;
}
-
- if (value)
- *value = fd->_ctx[index].value;
-
+
+ if (value)
+ *value = fd->_ctx[index].value1;
+
fd->_ctx[index].key = 0;
- fd->_ctx[index].value = 0;
+ fd->_ctx[index].value1 = 0;
out:
- return ret;
+ return ret;
}
-int
+int
fd_ctx_del (fd_t *fd, xlator_t *xlator, uint64_t *value)
{
int ret = 0;
- if (!fd || !xlator)
- return -1;
-
+ if (!fd || !xlator)
+ return -1;
+
LOCK (&fd->lock);
{
ret = __fd_ctx_del (fd, xlator, value);
@@ -695,18 +1004,18 @@ fd_dump (fd_t *fd, char *prefix)
if (!fd)
return;
-
+
memset(key, 0, sizeof(key));
- gf_proc_dump_build_key(key, prefix, "pid");
- gf_proc_dump_write(key, "%d", fd->pid);
- gf_proc_dump_build_key(key, prefix, "refcount");
- gf_proc_dump_write(key, "%d", fd->refcount);
- gf_proc_dump_build_key(key, prefix, "flags");
- gf_proc_dump_write(key, "%d", fd->flags);
+ gf_proc_dump_write("pid", "%llu", fd->pid);
+ gf_proc_dump_write("refcount", "%d", fd->refcount);
+ gf_proc_dump_write("flags", "%d", fd->flags);
+
if (fd->inode) {
- gf_proc_dump_build_key(key, prefix, "inode");
- gf_proc_dump_write(key, "%ld", fd->inode->ino);
+ gf_proc_dump_build_key (key, "inode", NULL);
+ gf_proc_dump_add_section(key);
+ inode_dump (fd->inode, key);
}
+
}
@@ -719,10 +1028,11 @@ fdentry_dump (fdentry_t *fdentry, char *prefix)
if (GF_FDENTRY_ALLOCATED != fdentry->next_free)
return;
- if (fdentry->fd)
+ if (fdentry->fd)
fd_dump(fdentry->fd, prefix);
}
+
void
fdtable_dump (fdtable_t *fdtable, char *prefix)
{
@@ -732,13 +1042,11 @@ fdtable_dump (fdtable_t *fdtable, char *prefix)
if (!fdtable)
return;
-
- ret = pthread_mutex_trylock (&fdtable->lock);
- if (ret) {
- gf_log ("fd", GF_LOG_WARNING, "Unable to acquire lock");
- return;
- }
+ ret = pthread_mutex_trylock (&fdtable->lock);
+
+ if (ret)
+ goto out;
memset(key, 0, sizeof(key));
gf_proc_dump_build_key(key, prefix, "refcount");
@@ -749,8 +1057,8 @@ fdtable_dump (fdtable_t *fdtable, char *prefix)
gf_proc_dump_write(key, "%d", fdtable->first_free);
for ( i = 0 ; i < fdtable->max_fds; i++) {
- if (GF_FDENTRY_ALLOCATED ==
- fdtable->fdentries[i].next_free) {
+ if (GF_FDENTRY_ALLOCATED ==
+ fdtable->fdentries[i].next_free) {
gf_proc_dump_build_key(key, prefix, "fdentry[%d]", i);
gf_proc_dump_add_section(key);
fdentry_dump(&fdtable->fdentries[i], key);
@@ -758,5 +1066,150 @@ fdtable_dump (fdtable_t *fdtable, char *prefix)
}
pthread_mutex_unlock(&fdtable->lock);
+
+out:
+ if (ret != 0)
+ gf_proc_dump_write ("Unable to dump the fdtable",
+ "(Lock acquistion failed) %p", fdtable);
+ return;
}
+
+void
+fd_ctx_dump (fd_t *fd, char *prefix)
+{
+ struct _fd_ctx *fd_ctx = NULL;
+ xlator_t *xl = NULL;
+ int i = 0;
+
+
+ if ((fd == NULL) || (fd->_ctx == NULL)) {
+ goto out;
+ }
+
+ LOCK (&fd->lock);
+ {
+ if (fd->_ctx != NULL) {
+ fd_ctx = GF_CALLOC (fd->xl_count, sizeof (*fd_ctx),
+ gf_common_mt_fd_ctx);
+ if (fd_ctx == NULL) {
+ goto unlock;
+ }
+
+ for (i = 0; i < fd->xl_count; i++) {
+ fd_ctx[i] = fd->_ctx[i];
+ }
+ }
+ }
+unlock:
+ UNLOCK (&fd->lock);
+
+ if (fd_ctx == NULL) {
+ goto out;
+ }
+
+ for (i = 0; i < fd->xl_count; i++) {
+ if (fd_ctx[i].xl_key) {
+ xl = (xlator_t *)(long)fd_ctx[i].xl_key;
+ if (xl->dumpops && xl->dumpops->fdctx)
+ xl->dumpops->fdctx (xl, fd);
+ }
+ }
+
+out:
+ GF_FREE (fd_ctx);
+
+ return;
+}
+
+void
+fdentry_dump_to_dict (fdentry_t *fdentry, char *prefix, dict_t *dict,
+ int *openfds)
+{
+ char key[GF_DUMP_MAX_BUF_LEN] = {0,};
+ int ret = -1;
+
+ if (!fdentry)
+ return;
+ if (!dict)
+ return;
+
+ if (GF_FDENTRY_ALLOCATED != fdentry->next_free)
+ return;
+
+ if (fdentry->fd) {
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.pid", prefix);
+ ret = dict_set_int32 (dict, key, fdentry->fd->pid);
+ if (ret)
+ return;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.refcount", prefix);
+ ret = dict_set_int32 (dict, key, fdentry->fd->refcount);
+ if (ret)
+ return;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.flags", prefix);
+ ret = dict_set_int32 (dict, key, fdentry->fd->flags);
+
+ (*openfds)++;
+ }
+ return;
+}
+
+void
+fdtable_dump_to_dict (fdtable_t *fdtable, char *prefix, dict_t *dict)
+{
+ char key[GF_DUMP_MAX_BUF_LEN] = {0,};
+ int i = 0;
+ int openfds = 0;
+ int ret = -1;
+
+ if (!fdtable)
+ return;
+ if (!dict)
+ return;
+
+ ret = pthread_mutex_trylock (&fdtable->lock);
+ if (ret)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.fdtable.refcount", prefix);
+ ret = dict_set_int32 (dict, key, fdtable->refcount);
+ if (ret)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.fdtable.maxfds", prefix);
+ ret = dict_set_uint32 (dict, key, fdtable->max_fds);
+ if (ret)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.fdtable.firstfree", prefix);
+ ret = dict_set_int32 (dict, key, fdtable->first_free);
+ if (ret)
+ goto out;
+
+ for (i = 0; i < fdtable->max_fds; i++) {
+ if (GF_FDENTRY_ALLOCATED ==
+ fdtable->fdentries[i].next_free) {
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.fdtable.fdentry%d",
+ prefix, i);
+ fdentry_dump_to_dict (&fdtable->fdentries[i], key,
+ dict, &openfds);
+ }
+ }
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.fdtable.openfds", prefix);
+ ret = dict_set_int32 (dict, key, openfds);
+
+out:
+ pthread_mutex_unlock (&fdtable->lock);
+ return;
+}