diff options
Diffstat (limited to 'libglusterfs/src/fd.c')
| -rw-r--r-- | libglusterfs/src/fd.c | 312 |
1 files changed, 264 insertions, 48 deletions
diff --git a/libglusterfs/src/fd.c b/libglusterfs/src/fd.c index 62a70c457..36cc4d056 100644 --- a/libglusterfs/src/fd.c +++ b/libglusterfs/src/fd.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2011 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 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" @@ -130,7 +121,7 @@ gf_fd_fdtable_alloc (void) } -fdentry_t * +static fdentry_t * __gf_fd_fdtable_get_all_fds (fdtable_t *fdtable, uint32_t *count) { fdentry_t *fdentries = NULL; @@ -168,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) { @@ -309,6 +347,54 @@ unlock_out: } +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); + + if ((fd != NULL) && (fde != NULL)) { + fd_unref (fd); + } +} + + fd_t * gf_fd_fdptr_get (fdtable_t *fdtable, int64_t fd) { @@ -401,7 +487,7 @@ fd_destroy (fd_t *fd) goto out; if (IA_ISDIR (fd->inode->ia_type)) { - for (i = 0; i < fd->xl_count; i++) { + for (i = 0; i < fd->xl_count; i++) { if (fd->_ctx[i].key) { xl = fd->_ctx[i].xl_key; old_THIS = THIS; @@ -427,8 +513,14 @@ fd_destroy (fd_t *fd) LOCK_DESTROY (&fd->lock); 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; + fd_lk_ctx_unref (fd->lk_ctx); mem_put (fd); out: return; @@ -463,7 +555,9 @@ fd_unref (fd_t *fd) fd_t * __fd_bind (fd_t *fd) { + list_del_init (&fd->inode_list); list_add (&fd->inode_list, &fd->inode->fd_list); + fd->inode->fd_count++; return fd; } @@ -488,7 +582,7 @@ fd_bind (fd_t *fd) static fd_t * -__fd_create (inode_t *inode, pid_t pid) +__fd_create (inode_t *inode, uint64_t pid) { fd_t *fd = NULL; @@ -505,11 +599,12 @@ __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) { - mem_put (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; @@ -518,6 +613,13 @@ __fd_create (inode_t *inode, pid_t pid) LOCK_INIT (&fd->lock); out: return fd; + +free_fd_ctx: + GF_FREE (fd->_ctx); +free_fd: + mem_put (fd); + + return NULL; } @@ -526,6 +628,21 @@ 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; @@ -538,7 +655,7 @@ out: static fd_t * -__fd_lookup (inode_t *inode, pid_t pid) +__fd_lookup (inode_t *inode, uint64_t pid) { fd_t *iter_fd = NULL; fd_t *fd = NULL; @@ -548,6 +665,12 @@ __fd_lookup (inode_t *inode, pid_t pid) 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; @@ -570,6 +693,25 @@ fd_lookup (inode_t *inode, pid_t pid) LOCK (&inode->lock); { + fd = __fd_lookup (inode, (uint64_t)pid); + } + UNLOCK (&inode->lock); + + return fd; +} + +fd_t * +fd_lookup_uint64 (inode_t *inode, uint64_t pid) +{ + fd_t *fd = NULL; + + if (!inode) { + gf_log_callingfn ("fd", GF_LOG_WARNING, "!inode"); + return NULL; + } + + LOCK (&inode->lock); + { fd = __fd_lookup (inode, pid); } UNLOCK (&inode->lock); @@ -577,25 +719,48 @@ fd_lookup (inode_t *inode, pid_t pid) 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; -fd_t * + 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 (inode, -1); + 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, -1); + fd = __fd_create (inode, 0); if (!fd) return NULL; + fd->anonymous = _gf_true; + __fd_bind (fd); - } - __fd_ref (fd); + __fd_ref (fd); + } return fd; } @@ -615,11 +780,28 @@ fd_anonymous (inode_t *inode) 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->pid == -1); + return (fd && fd->anonymous); } @@ -641,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; @@ -662,9 +847,33 @@ __fd_ctx_set (fd_t *fd, xlator_t *xlator, uint64_t value) } if (set_idx == -1) { - gf_log_callingfn ("", GF_LOG_WARNING, "%p %s", fd, xlator->name); - 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; @@ -797,9 +1006,16 @@ fd_dump (fd_t *fd, char *prefix) return; memset(key, 0, sizeof(key)); - gf_proc_dump_write("pid", "%d", fd->pid); + 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, "inode", NULL); + gf_proc_dump_add_section(key); + inode_dump (fd->inode, key); + } + } @@ -829,10 +1045,8 @@ fdtable_dump (fdtable_t *fdtable, char *prefix) 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"); @@ -852,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; } @@ -870,15 +1090,13 @@ 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) { 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]; } } @@ -890,7 +1108,7 @@ unlock: 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) @@ -899,9 +1117,7 @@ unlock: } out: - if (fd_ctx != NULL) { - GF_FREE (fd_ctx); - } + GF_FREE (fd_ctx); return; } |
