diff options
Diffstat (limited to 'libglusterfs/src/fd.c')
| -rw-r--r-- | libglusterfs/src/fd.c | 894 |
1 files changed, 612 insertions, 282 deletions
diff --git a/libglusterfs/src/fd.c b/libglusterfs/src/fd.c index 4bd30eee7..36cc4d056 100644 --- a/libglusterfs/src/fd.c +++ b/libglusterfs/src/fd.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2009 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. */ #include "fd.h" @@ -35,30 +26,7 @@ gf_fd_fdtable_expand (fdtable_t *fdtable, uint32_t nr); 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 int -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_ref (fd_t *fd); static int gf_fd_chain_fd_entries (fdentry_t *entries, uint32_t startidx, @@ -66,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. @@ -85,35 +55,35 @@ gf_fd_chain_fd_entries (fdentry_t *entries, uint32_t startidx, static int gf_fd_fdtable_expand (fdtable_t *fdtable, uint32_t nr) { - fdentry_t *oldfds = NULL; - uint32_t oldmax_fds = -1; + fdentry_t *oldfds = NULL; + uint32_t oldmax_fds = -1; int ret = -1; - if (fdtable == NULL || nr < 0) { - gf_log ("fd", GF_LOG_ERROR, "invalid argument"); + 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_power_of_two (nr + 1); - nr *= (1024 / sizeof (fdentry_t)); + 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; + oldfds = fdtable->fdentries; + oldmax_fds = fdtable->max_fds; - fdtable->fdentries = GF_CALLOC (nr, sizeof (fdentry_t), + fdtable->fdentries = GF_CALLOC (nr, sizeof (fdentry_t), gf_common_mt_fdentry_t); - if (!fdtable->fdentries) { + if (!fdtable->fdentries) { ret = ENOMEM; goto out; } - fdtable->max_fds = nr; + fdtable->max_fds = nr; - if (oldfds) { - uint32_t cpy = oldmax_fds * sizeof (fdentry_t); - memcpy (fdtable->fdentries, oldfds, cpy); - } + 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); @@ -123,40 +93,41 @@ gf_fd_fdtable_expand (fdtable_t *fdtable, uint32_t nr) * using the expanded table. */ fdtable->first_free = oldmax_fds; - GF_FREE (oldfds); + GF_FREE (oldfds); ret = 0; out: - return ret; + return ret; } fdtable_t * gf_fd_fdtable_alloc (void) { - fdtable_t *fdtable = NULL; + fdtable_t *fdtable = NULL; - fdtable = GF_CALLOC (1, sizeof (*fdtable), gf_common_mt_fdtable_t); - 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; } @@ -188,6 +159,53 @@ gf_fd_fdtable_get_all_fds (fdtable_t *fdtable, uint32_t *count) } +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) { @@ -199,15 +217,17 @@ gf_fd_fdtable_destroy (fdtable_t *fdtable) 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); - GF_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++) { @@ -218,53 +238,52 @@ gf_fd_fdtable_destroy (fdtable_t *fdtable) } GF_FREE (fdentries); - pthread_mutex_destroy (&fdtable->lock); - GF_FREE (fdtable); - } + pthread_mutex_destroy (&fdtable->lock); + GF_FREE (fdtable); + } } 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; - } + 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: + 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 @@ -273,39 +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 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 == -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 ("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); - { + 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) @@ -314,85 +337,133 @@ 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; + fd_t *fdptr = NULL; - if (fdtable == NULL || fd < 0) { - gf_log ("fd", GF_LOG_ERROR, "invalid argument"); - errno = EINVAL; - return 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 ("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); + pthread_mutex_lock (&fdtable->lock); + { + fdptr = fdtable->fdentries[fd].fd; + if (fdptr) { + fd_ref (fdptr); + } + } + pthread_mutex_unlock (&fdtable->lock); - return fdptr; + return fdptr; } fd_t * -_fd_ref (fd_t *fd) +__fd_ref (fd_t *fd) { - ++fd->refcount; + ++fd->refcount; - return fd; + 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; } @@ -400,55 +471,57 @@ static void fd_destroy (fd_t *fd) { xlator_t *xl = NULL; - int i = 0; + int i = 0; xlator_t *old_THIS = NULL; - struct mem_pool *tmp_pool = 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; - - tmp_pool = fd->inode->table->fd_mem_pool; + 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; + 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); + if (xl->cbks->releasedir) + xl->cbks->releasedir (xl, fd); THIS = old_THIS; - } - } + } + } } else { - for (i = 0; i < fd->xl_count; i++) { - if (fd->_ctx[i].key) { - xl = fd->_ctx[i].xl_key; + 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); + if (xl->cbks->release) + xl->cbks->release (xl, fd); THIS = old_THIS; - } - } + } + } } LOCK_DESTROY (&fd->lock); - GF_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; - mem_put (tmp_pool,fd); - tmp_pool = NULL; + fd_lk_ctx_unref (fd->lk_ctx); + mem_put (fd); out: return; } @@ -460,13 +533,13 @@ 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); @@ -480,56 +553,41 @@ fd_unref (fd_t *fd) fd_t * -fd_bind (fd_t *fd) +__fd_bind (fd_t *fd) { - inode_t *inode = NULL; - - if (!fd || !fd->inode) { - gf_log_callingfn ("fd", GF_LOG_ERROR, "!fd || !fd->inode"); - return NULL; - } - inode = fd->inode; - - LOCK (&inode->lock); - { - list_add (&fd->inode_list, &inode->fd_list); - } - UNLOCK (&inode->lock); + list_del_init (&fd->inode_list); + list_add (&fd->inode_list, &fd->inode->fd_list); + fd->inode->fd_count++; return fd; } -void -fd_unref_unbind (fd_t *fd) +fd_t * +fd_bind (fd_t *fd) { - assert (fd->refcount); + if (!fd || !fd->inode) { + gf_log_callingfn ("fd", GF_LOG_ERROR, "!fd || !fd->inode"); + return NULL; + } LOCK (&fd->inode->lock); { - --fd->refcount; - /* Better know what you're doing with this function - * because it does not do what fd_destroy does when - * refcount goes to 0. - * Make sure you only call this when you know there are - * pending refs on the fd. - */ - assert (fd->refcount); - list_del_init (&fd->inode_list); + fd = __fd_bind (fd); } UNLOCK (&fd->inode->lock); - return; + 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; } @@ -541,60 +599,211 @@ fd_create (inode_t *inode, pid_t pid) fd->_ctx = GF_CALLOC (1, (sizeof (struct _fd_ctx) * fd->xl_count), gf_common_mt_fd_ctx); - if (!fd->_ctx) { - GF_FREE (fd); - fd = NULL; - goto out; - } + 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); -out: + 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) + 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) @@ -614,9 +823,12 @@ fd_list_empty (inode_t *inode) 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; @@ -635,15 +847,40 @@ __fd_ctx_set (fd_t *fd, xlator_t *xlator, uint64_t value) } 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].xl_key = xlator; fd->_ctx[set_idx].value1 = value; out: - return ret; + return ret; } @@ -652,8 +889,10 @@ 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); { @@ -668,11 +907,11 @@ fd_ctx_set (fd_t *fd, xlator_t *xlator, uint64_t value) 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; + if (!fd || !xlator) + return -1; for (index = 0; index < fd->xl_count; index++) { if (fd->_ctx[index].xl_key == xlator) @@ -688,7 +927,7 @@ __fd_ctx_get (fd_t *fd, xlator_t *xlator, uint64_t *value) *value = fd->_ctx[index].value1; out: - return ret; + return ret; } @@ -697,8 +936,8 @@ 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); { @@ -713,11 +952,11 @@ fd_ctx_get (fd_t *fd, xlator_t *xlator, uint64_t *value) 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; + if (!fd || !xlator) + return -1; for (index = 0; index < fd->xl_count; index++) { if (fd->_ctx[index].xl_key == xlator) @@ -736,7 +975,7 @@ __fd_ctx_del (fd_t *fd, xlator_t *xlator, uint64_t *value) fd->_ctx[index].value1 = 0; out: - return ret; + return ret; } @@ -745,8 +984,8 @@ 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); { @@ -767,16 +1006,16 @@ fd_dump (fd_t *fd, char *prefix) 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); } + } @@ -804,12 +1043,10 @@ fdtable_dump (fdtable_t *fdtable, char *prefix) if (!fdtable) return; - ret = pthread_mutex_trylock (&fdtable->lock); + ret = pthread_mutex_trylock (&fdtable->lock); - if (ret) { - gf_log ("fd", GF_LOG_WARNING, "Unable to acquire lock"); - return; - } + if (ret) + goto out; memset(key, 0, sizeof(key)); gf_proc_dump_build_key(key, prefix, "refcount"); @@ -821,7 +1058,7 @@ fdtable_dump (fdtable_t *fdtable, char *prefix) for ( i = 0 ; i < fdtable->max_fds; i++) { if (GF_FDENTRY_ALLOCATED == - fdtable->fdentries[i].next_free) { + 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); @@ -829,6 +1066,12 @@ 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; } @@ -838,7 +1081,7 @@ 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; @@ -847,28 +1090,25 @@ fd_ctx_dump (fd_t *fd, char *prefix) LOCK (&fd->lock); { if (fd->_ctx != NULL) { - fd_ctx = GF_CALLOC (fd->inode->table->xl->graph->xl_count, - sizeof (*fd_ctx), + fd_ctx = GF_CALLOC (fd->xl_count, sizeof (*fd_ctx), gf_common_mt_fd_ctx); if (fd_ctx == NULL) { - gf_log ("fd", GF_LOG_ERROR, "out of memory"); goto unlock; } - for (i = 0; i < fd->inode->table->xl->graph->xl_count; - i++) { + 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->inode->table->xl->graph->xl_count; i++) { + 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) @@ -877,9 +1117,99 @@ unlock: } out: - if (fd_ctx != NULL) { - GF_FREE (fd_ctx); + 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; } |
